2010-06-21 Zoltan Varga <vargaz@gmail.com>
[mono.git] / mcs / class / System.Web / System.Web.UI.WebControls / Calendar.cs
1 //
2 // System.Web.UI.WebControls.Calendar.cs
3 //
4 // Authors:
5 //    Jordi Mas i Hernandez (jordi@ximian.com)
6 //
7 // (C) 2005 Novell, Inc (http://www.novell.com)
8 //
9 //
10 //
11 // Permission is hereby granted, free of charge, to any person obtaining
12 // a copy of this software and associated documentation files (the
13 // "Software"), to deal in the Software without restriction, including
14 // without limitation the rights to use, copy, modify, merge, publish,
15 // distribute, sublicense, and/or sell copies of the Software, and to
16 // permit persons to whom the Software is furnished to do so, subject to
17 // the following conditions:
18 //
19 // The above copyright notice and this permission notice shall be
20 // included in all copies or substantial portions of the Software.
21 //
22 // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
23 // EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
24 // MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
25 // NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
26 // LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
27 // OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
28 // WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
29 //
30 //
31
32 using System.Globalization;
33 using System.Collections;
34 using System.ComponentModel;
35 using System.Drawing;
36 using System.Security.Permissions;
37 using System.Threading;
38 using System.Text;
39 using System.Web.Util;
40
41 namespace System.Web.UI.WebControls {
42         // CAS
43         [AspNetHostingPermissionAttribute (SecurityAction.LinkDemand, Level = AspNetHostingPermissionLevel.Minimal)]
44         [AspNetHostingPermissionAttribute (SecurityAction.InheritanceDemand, Level = AspNetHostingPermissionLevel.Minimal)]
45         // attributes
46         [DataBindingHandler("System.Web.UI.Design.WebControls.CalendarDataBindingHandler, " + Consts.AssemblySystem_Design)]
47         [DefaultEvent("SelectionChanged")]
48         [DefaultProperty("SelectedDate")]
49         [Designer("System.Web.UI.Design.WebControls.CalendarDesigner, " + Consts.AssemblySystem_Design, "System.ComponentModel.Design.IDesigner")]
50 #if NET_2_0
51         [ControlValueProperty ("SelectedDate", "1/1/0001 12:00:00 AM")]
52         [SupportsEventValidation]
53 #endif          
54         public class Calendar : WebControl, IPostBackEventHandler
55         {
56                 TableItemStyle dayHeaderStyle;
57                 TableItemStyle dayStyle;
58                 TableItemStyle nextPrevStyle;
59                 TableItemStyle otherMonthDayStyle;
60                 TableItemStyle selectedDayStyle;
61                 TableItemStyle titleStyle;
62                 TableItemStyle todayDayStyle;
63                 TableItemStyle selectorStyle;
64                 TableItemStyle weekendDayStyle;
65                 DateTimeFormatInfo dateInfo;
66                 SelectedDatesCollection selectedDatesCollection;
67                 ArrayList dateList;
68                 DateTime today = DateTime.Today;
69                 static DateTime dateZenith  = new DateTime (2000, 1,1);
70                 const int daysInAWeek = 7;
71                 static readonly object DayRenderEvent = new object ();
72                 static readonly object SelectionChangedEvent = new object ();
73                 static readonly object VisibleMonthChangedEvent = new object ();
74
75                 public Calendar ()
76                 {
77                 }
78
79 #if NET_2_0
80                 [Localizable (true)]
81                 [DefaultValue ("")]
82                 [WebSysDescription ("")]
83                 [WebCategoryAttribute ("Appearance")]
84                 public virtual string Caption 
85                 {
86                         get {
87                                 return ViewState.GetString ("Caption", "");
88                         }
89                         set {
90                                 ViewState["Caption"] = value;
91                         }
92                 }
93
94                 [DefaultValue (TableCaptionAlign.NotSet)]
95                 [WebSysDescription ("")]
96                 [WebCategoryAttribute ("Accessibility")]
97                 public virtual TableCaptionAlign CaptionAlign 
98                 {
99                         get {
100                                 return (TableCaptionAlign)ViewState.GetInt ("CaptionAlign", (int)TableCaptionAlign.NotSet);
101                         }
102                         set {
103                                 ViewState ["CaptionAlign"] = value;
104                         }
105                 }
106 #endif
107
108 #if ONLY_1_1
109                 [Bindable(true)]
110 #endif          
111                 [DefaultValue(2)]
112                 [WebSysDescription ("")]
113                 [WebCategory ("Layout")]
114                 public int CellPadding {
115                         get {
116                                 return ViewState.GetInt ("CellPadding", 2);
117                         }
118
119                         set {
120                                 if (value < -1)
121                                         throw new ArgumentOutOfRangeException ("The specified cell padding is less than -1.");
122
123                                 ViewState ["CellPadding"] = value;
124                         }
125                 }
126
127 #if ONLY_1_1
128                 [Bindable(true)]
129 #endif          
130                 [DefaultValue(0)]
131                 [WebSysDescription ("")]
132                 [WebCategory ("Layout")]
133                 public int CellSpacing {
134                         get {
135                                 return ViewState.GetInt ("CellSpacing", 0);
136                         }
137
138                         set {
139                                 if (value < -1)
140                                         throw new ArgumentOutOfRangeException ("The specified cell spacing is less than -1");
141
142                                 ViewState ["CellSpacing"] = value;
143                         }
144                 }
145
146                 [PersistenceMode(PersistenceMode.InnerProperty)]
147                 [NotifyParentProperty(true)]
148                 [DesignerSerializationVisibility(DesignerSerializationVisibility.Content)]
149                 [WebSysDescription ("")]
150                 [WebCategory ("Style")]
151                 public TableItemStyle DayHeaderStyle {
152                         get {
153                                 if (dayHeaderStyle == null) {
154                                         dayHeaderStyle = new TableItemStyle ();
155                                         if (IsTrackingViewState)
156                                                 dayHeaderStyle.TrackViewState ();
157                                 }
158
159                                 return dayHeaderStyle;
160                         }
161                 }
162
163 #if ONLY_1_1
164                 [Bindable(true)]
165 #endif          
166                 [DefaultValue(DayNameFormat.Short)]
167                 [WebSysDescription ("")]
168                 [WebCategory ("Appearance")]
169                 public DayNameFormat DayNameFormat {
170                         get {
171                                 return (DayNameFormat) ViewState.GetInt ("DayNameFormat", (int) DayNameFormat.Short);
172                         }
173
174                         set {
175                                 if (value != DayNameFormat.FirstLetter && value != DayNameFormat.FirstTwoLetters &&
176                                         value != DayNameFormat.Full && value != DayNameFormat.Short && value != DayNameFormat.Shortest) {
177                                         throw new ArgumentOutOfRangeException ("The specified day name format is not one of the DayNameFormat values.");
178                                 }
179
180                                 ViewState ["DayNameFormat"] = value;
181                         }
182                 }
183
184                 [DefaultValue(null)]
185                 [DesignerSerializationVisibility(DesignerSerializationVisibility.Content)]
186                 [NotifyParentProperty(true)]
187                 [PersistenceMode(PersistenceMode.InnerProperty)]
188                 [WebSysDescription ("")]
189                 [WebCategory ("Style")]
190                 public TableItemStyle DayStyle {
191                         get {
192                                 if (dayStyle == null) {
193                                         dayStyle = new TableItemStyle ();
194                                         if (IsTrackingViewState)
195                                                 dayStyle.TrackViewState ();
196                                 }
197
198                                 return dayStyle;
199                         }
200                 }
201
202 #if ONLY_1_1
203                 [Bindable(true)]
204 #endif          
205                 [DefaultValue(FirstDayOfWeek.Default)]
206                 [WebSysDescription ("")]
207                 [WebCategory ("Appearance")]
208                 public FirstDayOfWeek FirstDayOfWeek {
209                         get {
210                                 return (FirstDayOfWeek) ViewState.GetInt ("FirstDayOfWeek", (int) FirstDayOfWeek.Default);
211                         }
212
213                         set {
214                                 if (value < FirstDayOfWeek.Sunday || value > FirstDayOfWeek.Default) {
215                                         throw new ArgumentOutOfRangeException ("The specified day name format is not one of the DayNameFormat values.");
216                                 }
217
218                                 ViewState ["FirstDayOfWeek"] = value;
219                         }
220                 }
221
222 #if ONLY_1_1
223                 [Bindable(true)]
224 #endif          
225                 [DefaultValue("&gt;")]
226 #if NET_2_0
227                 [Localizable (true)]
228 #endif
229                 [WebSysDescription ("")]
230                 [WebCategory ("Appearance")]
231                 public string NextMonthText {
232                         get {
233                                 return ViewState.GetString ("NextMonthText", "&gt;");
234                         }
235
236                         set {
237                                 ViewState ["NextMonthText"] = value;
238                         }
239                 }
240
241 #if ONLY_1_1
242                 [Bindable(true)]
243 #endif          
244                 [DefaultValue(NextPrevFormat.CustomText)]
245                 [WebSysDescription ("")]
246                 [WebCategory ("Appearance")]
247                 public NextPrevFormat NextPrevFormat {
248                         get {
249                                 return (NextPrevFormat) ViewState.GetInt ("NextPrevFormat", (int) NextPrevFormat.CustomText);
250                         }
251
252                         set {
253                                 if (value != NextPrevFormat.CustomText && value != NextPrevFormat.ShortMonth && value != NextPrevFormat.FullMonth) {
254                                         throw new ArgumentOutOfRangeException ("The specified day name format is not one of the DayNameFormat values.");
255                                 }
256
257                                 ViewState ["NextPrevFormat"] = value;
258                         }
259                 }
260
261                 [DesignerSerializationVisibility(DesignerSerializationVisibility.Content)]
262                 [NotifyParentProperty(true)]
263                 [PersistenceMode(PersistenceMode.InnerProperty)]
264                 [WebSysDescription ("")]
265                 [WebCategory ("Style")]
266                 public TableItemStyle NextPrevStyle {
267                         get {
268                                 if (nextPrevStyle == null) {
269                                         nextPrevStyle = new TableItemStyle ();
270                                         if (IsTrackingViewState)
271                                                 nextPrevStyle.TrackViewState ();
272                                 }
273
274                                 return nextPrevStyle;
275                         }
276                 }
277
278                 [DefaultValue(null)]
279                 [NotifyParentProperty(true)]
280                 [DesignerSerializationVisibility(DesignerSerializationVisibility.Content)]
281                 [PersistenceMode(PersistenceMode.InnerProperty)]
282                 [WebSysDescription ("")]
283                 [WebCategory ("Style")]
284                 public TableItemStyle OtherMonthDayStyle {
285                         get {
286                                 if (otherMonthDayStyle == null) {
287                                         otherMonthDayStyle = new TableItemStyle ();
288                                         if (IsTrackingViewState)
289                                                 otherMonthDayStyle.TrackViewState ();
290                                 }
291
292                                 return otherMonthDayStyle;
293                         }
294                 }
295
296 #if ONLY_1_1
297                 [Bindable(true)]
298 #endif          
299                 [DefaultValue("&lt;")]
300 #if NET_2_0
301                 [Localizable (true)]
302 #endif
303                 [WebSysDescription ("")]
304                 [WebCategory ("Appearance")]
305                 public string PrevMonthText {
306                         get {
307                                 return ViewState.GetString ("PrevMonthText", "&lt;");
308                         }
309
310                         set {
311                                 ViewState ["PrevMonthText"] = value;
312                         }
313                 }
314
315 #if NET_2_0
316                 [Bindable(true, BindingDirection.TwoWay)]
317 #else
318                 [Bindable(true)]
319 #endif          
320                 [DefaultValue("1/1/0001 12:00:00 AM")]
321                 [WebSysDescription ("")]
322                 [WebCategory ("Appearance")]
323                 public DateTime SelectedDate {
324                         get {
325                                 if (SelectedDates.Count > 0)
326                                         return SelectedDates [0];
327
328                                 return DateTime.MinValue;
329                         }
330
331                         set {
332                                 SelectedDates.SelectRange (value, value);
333                         }
334                 }
335
336                 [Browsable(false)]
337                 [DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden)]
338                 [WebSysDescription ("")]
339                 [WebCategory ("Appearance")]
340                 public SelectedDatesCollection SelectedDates {
341                         get {
342                                 if (dateList == null)
343                                         dateList = new ArrayList ();
344
345                                 if (selectedDatesCollection == null)
346                                         selectedDatesCollection = new SelectedDatesCollection (dateList);
347
348                                 return selectedDatesCollection;
349                         }
350                 }
351
352                 [DefaultValue(null)]
353                 [DesignerSerializationVisibility(DesignerSerializationVisibility.Content)]
354                 [NotifyParentProperty(true)]
355                 [PersistenceMode(PersistenceMode.InnerProperty)]
356                 [WebSysDescription ("")]
357                 [WebCategory ("Style")]
358                 public TableItemStyle SelectedDayStyle {
359                         get {
360                                 if (selectedDayStyle == null) {
361                                         selectedDayStyle = new TableItemStyle ();
362                                         if (IsTrackingViewState)
363                                                 selectedDayStyle.TrackViewState ();
364                                 }
365
366                                 return selectedDayStyle;
367                         }
368                 }
369
370 #if ONLY_1_1
371                 [Bindable(true)]
372 #endif          
373                 [DefaultValue(CalendarSelectionMode.Day)]
374                 [WebSysDescription ("")]
375                 [WebCategory ("Behavior")]
376                 public CalendarSelectionMode SelectionMode {
377                         get {
378                                 return (CalendarSelectionMode) ViewState.GetInt ("SelectionMode", (int) CalendarSelectionMode.Day);
379                         }
380
381                         set {
382                                 if (value != CalendarSelectionMode.Day  && value != CalendarSelectionMode.DayWeek &&
383                                         value != CalendarSelectionMode.DayWeekMonth  && value != CalendarSelectionMode.None) {
384                                         throw new ArgumentOutOfRangeException ("The specified selection mode is not one of the CalendarSelectionMode values.");
385                                 }
386                                 ViewState ["SelectionMode"] = value;
387                         }
388                 }
389
390 #if ONLY_1_1
391                 [Bindable(true)]
392 #endif          
393                 [DefaultValue("&gt;&gt;")]
394 #if NET_2_0
395                 [Localizable (true)]
396 #endif
397                 [WebSysDescription ("")]
398                 [WebCategory ("Appearance")]
399                 public string SelectMonthText {
400                         get {
401                                 return ViewState.GetString ("SelectMonthText", "&gt;&gt;");
402                         }
403
404                         set {
405                                 ViewState ["SelectMonthText"] = value;
406                         }
407                 }
408
409                 [DesignerSerializationVisibility(DesignerSerializationVisibility.Content)]
410                 [NotifyParentProperty(true)]
411                 [PersistenceMode(PersistenceMode.InnerProperty)]
412                 [WebSysDescription ("")]
413                 [WebCategory ("Style")]
414                 public TableItemStyle SelectorStyle {
415                         get {
416                                 if (selectorStyle == null) {
417                                          selectorStyle = new TableItemStyle ();
418                                         if (IsTrackingViewState)
419                                                 selectorStyle.TrackViewState ();
420                                 }
421
422                                 return selectorStyle;
423                         }
424                 }
425
426 #if ONLY_1_1
427                 [Bindable(true)]
428 #endif          
429                 [DefaultValue("&gt;")]
430 #if NET_2_0             
431                 [Localizable (true)]
432 #endif          
433                 [WebSysDescription ("")]
434                 [WebCategory ("Appearance")]
435                 public string SelectWeekText {
436                         get {
437                                 return ViewState.GetString ("SelectWeekText", "&gt;");
438                         }
439
440                         set {
441                                 ViewState ["SelectWeekText"] = value;
442                         }
443                 }
444
445 #if ONLY_1_1
446                 [Bindable(true)]
447 #endif          
448                 [DefaultValue(true)]
449                 [WebSysDescription ("")]
450                 [WebCategory ("Appearance")]
451                 public bool ShowDayHeader {
452                         get {
453                                 return ViewState.GetBool ("ShowDayHeader", true);
454                         }
455
456                         set {
457                                 ViewState ["ShowDayHeader"] = value;
458                         }
459                 }
460
461 #if ONLY_1_1
462                 [Bindable(true)]
463 #endif          
464                 [DefaultValue(false)]
465                 [WebSysDescription ("")]
466                 [WebCategory ("Appearance")]
467                 public bool ShowGridLines {
468                         get {
469                                 return ViewState.GetBool ("ShowGridLines", false);
470                         }
471
472                         set {
473                                 ViewState ["ShowGridLines"] = value;
474                         }
475                 }
476
477 #if ONLY_1_1
478                 [Bindable(true)]
479 #endif          
480                 [DefaultValue(true)]
481                 [WebSysDescription ("")]
482                 [WebCategory ("Appearance")]
483                 public bool ShowNextPrevMonth {
484                         get {
485                                 return ViewState.GetBool ("ShowNextPrevMonth", true);
486                         }
487
488                         set {
489                                 ViewState ["ShowNextPrevMonth"] = value;
490                         }
491                 }
492
493 #if ONLY_1_1
494                 [Bindable(true)]
495 #endif          
496                 [DefaultValue(true)]
497                 [WebSysDescription ("")]
498                 [WebCategory ("Appearance")]
499                 public bool ShowTitle {
500                         get {
501                                 return ViewState.GetBool ("ShowTitle", true);
502                         }
503
504                         set {
505                                 ViewState ["ShowTitle"] = value;
506                         }
507                 }
508
509 #if ONLY_1_1
510                 [Bindable(true)]
511 #endif          
512                 [DefaultValue(TitleFormat.MonthYear)]
513                 [WebSysDescription ("")]
514                 [WebCategory ("Appearance")]
515                 public TitleFormat TitleFormat {
516                         get {
517                                 return (TitleFormat) ViewState.GetInt ("TitleFormat", (int) TitleFormat.MonthYear);
518                         }
519
520                         set {
521                                 if (value != TitleFormat.Month && value != TitleFormat.MonthYear) {
522                                         throw new ArgumentOutOfRangeException ("The specified title format is not one of the TitleFormat values.");
523                                 }
524
525                                 ViewState ["TitleFormat"] = value;
526                         }
527                 }
528
529                 [DesignerSerializationVisibility(DesignerSerializationVisibility.Content)]
530                 [NotifyParentProperty(true)]
531                 [PersistenceMode(PersistenceMode.InnerProperty)]
532                 [WebSysDescription ("")]
533                 [WebCategory ("Style")]
534                 public TableItemStyle TitleStyle {
535                         get {
536                                 if (titleStyle == null) {
537                                         titleStyle = new TableItemStyle ();
538                                         if (IsTrackingViewState)
539                                                 titleStyle.TrackViewState ();
540                                 }
541
542                                 return titleStyle;
543                         }
544                 }
545
546                 [DefaultValue(null)]
547                 [DesignerSerializationVisibility(DesignerSerializationVisibility.Content)]
548                 [NotifyParentProperty(true)]
549                 [PersistenceMode(PersistenceMode.InnerProperty)]
550                 [WebSysDescription ("")]
551                 [WebCategory ("Style")]
552                 public TableItemStyle TodayDayStyle {
553                         get {
554                                 if (todayDayStyle == null) {
555                                         todayDayStyle = new TableItemStyle ();
556                                         if (IsTrackingViewState)
557                                                 todayDayStyle.TrackViewState ();
558                                 }
559
560                                 return todayDayStyle;
561                         }
562                 }
563
564 #if ONLY_1_1
565                 [Bindable(true)]
566 #endif          
567                 [Browsable(false)]
568                 [DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden)]
569                 [WebSysDescription ("")]
570                 [WebCategory ("Style")]
571                 public DateTime TodaysDate {
572                         get {
573                                 object obj = ViewState ["TodaysDate"];
574
575                                 if (obj != null)
576                                         return (DateTime) obj;
577
578                                 return today;
579                         }
580
581                         set {
582                                 ViewState ["TodaysDate"] = value.Date;
583                         }
584                 }
585
586 #if NET_2_0
587                 [DefaultValue (true)]
588                 [WebSysDescription ("")]
589                 [WebCategoryAttribute ("Accessibility")]
590                 public virtual bool UseAccessibleHeader 
591                 {
592                         get {
593                                 return ViewState.GetBool ("UseAccessibleHeader", true);
594                         }
595                         set {
596                                 ViewState ["UseAccessibleHeader"] = value;
597                         }
598                 }
599 #endif          
600
601                 [Bindable(true)]
602                 [DefaultValue("1/1/0001 12:00:00 AM")]
603                 [WebSysDescription ("")]
604                 [WebCategory ("Style")]
605                 public DateTime VisibleDate {
606                         get {
607                                 object obj = ViewState ["VisibleDate"];
608
609                                 if (obj != null)
610                                         return (DateTime) obj;
611
612                                 return DateTime.MinValue;
613                         }
614
615                         set {
616                                 ViewState ["VisibleDate"] = value.Date;
617                         }
618                 }
619
620                 [DesignerSerializationVisibility(DesignerSerializationVisibility.Content)]
621                 [NotifyParentProperty(true)]
622                 [PersistenceMode(PersistenceMode.InnerProperty)]
623                 [WebSysDescription ("")]
624                 [WebCategory ("Style")]
625                 public TableItemStyle WeekendDayStyle {
626                         get {
627                                 if (weekendDayStyle == null) {
628                                         weekendDayStyle = new TableItemStyle ();
629                                         if (IsTrackingViewState)
630                                                 weekendDayStyle.TrackViewState ();
631                                 }
632
633                                 return weekendDayStyle;
634                         }
635                 }
636
637
638                 // Private properties
639                 DateTimeFormatInfo DateInfo {
640                         get {
641                                 if (dateInfo == null)
642                                         dateInfo = Thread.CurrentThread.CurrentCulture.DateTimeFormat;
643
644                                 return dateInfo;
645                         }
646                 }
647                 
648                 DateTime DisplayDate {
649                         get {
650                                 DateTime dateTime = VisibleDate;
651                                 if (dateTime == DateTime.MinValue) // If visibledate is still the default value
652                                         dateTime = TodaysDate;
653
654                                 return dateTime;
655                         }
656                 }
657
658                 DayOfWeek DisplayFirstDayOfWeek {
659                         get {
660                                 if (FirstDayOfWeek != FirstDayOfWeek.Default)
661                                         return (DayOfWeek)  FirstDayOfWeek;
662
663                                 return (DayOfWeek) DateInfo.FirstDayOfWeek;
664                         }
665                 }
666
667                 protected override ControlCollection CreateControlCollection ()
668                 {
669                         return base.CreateControlCollection ();
670                 }
671
672                 protected bool HasWeekSelectors (CalendarSelectionMode selectionMode)
673                 {
674                         if (selectionMode == CalendarSelectionMode.DayWeek || selectionMode == CalendarSelectionMode.DayWeekMonth)
675                                 return true;
676
677                         return false;
678                 }
679                 
680 #if NET_2_0
681                 void IPostBackEventHandler.RaisePostBackEvent (string eventArgument)
682                 {
683                         RaisePostBackEvent (eventArgument);
684                 }
685
686                 protected virtual void RaisePostBackEvent (string arg)
687 #else
688                 void IPostBackEventHandler.RaisePostBackEvent (string arg)
689 #endif
690                 {
691 #if NET_2_0
692                         ValidateEvent (UniqueID, arg);
693 #endif
694                         if (arg.Length < 1)
695                                 return;
696
697                         if (arg[0] == 'V') { // Goes to Next or Previous month
698                                 DateTime prev = VisibleDate;
699                                 int days = Int32.Parse (arg.Substring (1));
700                                 DateTime dt = GetGlobalCalendar().AddDays (dateZenith, days);
701                                 VisibleDate = dt;
702                                 OnVisibleMonthChanged (VisibleDate, prev);
703                                 return;
704                         }
705
706                         if (arg[0] == 'R') { // Selects a range of dates
707                                 string num, date, days;
708                                 num = arg.Substring (1);
709                                 days = num.Substring (num.Length - 2, 2);
710                                 date = num.Substring (0, num.Length - 2);
711                                 DateTime d = GetGlobalCalendar().AddDays (dateZenith, Int32.Parse (date));
712                                 SelectedDates.SelectRange (d, d.AddDays (Int32.Parse (days)));
713                                 OnSelectionChanged ();
714                                 return;
715                         }
716
717                         // Selects a single day
718                         int daysFromZenith = Int32.Parse (arg);
719                         DateTime day = GetGlobalCalendar().AddDays (dateZenith, daysFromZenith);
720                         SelectedDates.SelectRange (day, day);
721                         OnSelectionChanged ();
722                 }
723
724                 protected override void LoadViewState (object savedState)
725                 {
726                         object [] states = (object []) savedState;
727
728                         if (states [0] != null)
729                                  base.LoadViewState (states [0]);
730
731                         if (states [1] != null)
732                                 DayHeaderStyle.LoadViewState (states [1]);
733
734                         if (states [2] != null)
735                                 DayStyle.LoadViewState (states [2]);
736
737                         if (states [3] != null)
738                                 NextPrevStyle.LoadViewState (states [3]);
739
740                         if (states [4] != null)
741                                 OtherMonthDayStyle.LoadViewState (states [4]);
742
743                         if (states [5] != null)
744                                 SelectedDayStyle.LoadViewState (states [5]);
745
746                         if (states [6] != null)
747                                 TitleStyle.LoadViewState (states [6]);
748
749                         if (states [7] != null)
750                                 TodayDayStyle.LoadViewState (states [7]);
751
752                         if (states [8] != null)
753                                 SelectorStyle.LoadViewState (states [8]);
754
755                         if (states [9] != null)
756                                 WeekendDayStyle.LoadViewState (states [9]);
757
758                         ArrayList array = (ArrayList) ViewState ["SelectedDates"];
759                         if (array != null) {
760                                 dateList = array;
761                                 selectedDatesCollection = new SelectedDatesCollection (dateList);
762                         }
763                 }
764
765                 protected virtual void OnDayRender (TableCell cell, CalendarDay day)
766                 {
767                         DayRenderEventHandler eh = (DayRenderEventHandler) (Events [DayRenderEvent]);
768                         if (eh != null)
769 #if NET_2_0
770                                 if (Page != null)
771                                         eh (this, new DayRenderEventArgs (cell, day, Page.ClientScript.GetPostBackClientHyperlink (this, GetDaysFromZenith (day.Date).ToString (), true)));
772                                 else
773 #endif
774                                 eh (this, new DayRenderEventArgs (cell, day));
775                 }
776
777 #if NET_2_0
778                 protected internal
779 #else           
780                 protected
781 #endif          
782                 override void OnPreRender (EventArgs e)
783                 {
784                         base.OnPreRender (e);
785                 }
786
787                 protected virtual void OnSelectionChanged ()
788                 {
789                         EventHandler eh = (EventHandler) (Events [SelectionChangedEvent]);
790                         if (eh != null)
791                                 eh (this, EventArgs.Empty);
792                 }
793
794                 protected virtual void OnVisibleMonthChanged (DateTime newDate,  DateTime previousDate)
795                 {
796                         MonthChangedEventHandler eh = (MonthChangedEventHandler) (Events [VisibleMonthChangedEvent]);
797                         if (eh != null)
798                                 eh (this, new MonthChangedEventArgs (newDate, previousDate));
799                 }
800
801 #if NET_2_0
802                 protected internal
803 #else           
804                 protected
805 #endif          
806                 override void Render (HtmlTextWriter writer)
807                 {
808                         TableStyle ts = new TableStyle ();
809                         ts.CellSpacing = CellSpacing;
810                         ts.CellPadding = CellPadding;
811                         ts.BorderWidth = 1;
812                         if (ControlStyleCreated)
813                                 ts.CopyFrom (ControlStyle);
814                         if (ShowGridLines)
815                                 ts.GridLines = GridLines.Both;
816                         ts.AddAttributesToRender (writer);
817                         writer.AddAttribute (HtmlTextWriterAttribute.Id, ClientID);
818                         writer.RenderBeginTag (HtmlTextWriterTag.Table);
819
820 #if NET_2_0
821                         if (Caption != "")
822                                 WriteCaption (writer);
823 #endif
824
825                         if (ShowTitle)
826                                 WriteTitle (writer);
827
828                         if (ShowDayHeader)
829                                 WriteDayHeader (writer);
830
831                         WriteDays (writer);
832
833                         writer.RenderEndTag ();
834                 }
835
836                 protected override object SaveViewState ()
837                 {
838                         object [] states = new object [10];
839
840                         if (dayHeaderStyle != null)
841                                 states [1] = dayHeaderStyle.SaveViewState ();
842
843                         if (dayStyle != null)
844                                 states [2] = dayStyle.SaveViewState ();
845
846                         if (nextPrevStyle != null)
847                                 states [3] = nextPrevStyle.SaveViewState ();
848
849                         if (otherMonthDayStyle != null)
850                                 states [4] = otherMonthDayStyle.SaveViewState ();
851
852                         if (selectedDayStyle != null)
853                                 states [5] = selectedDayStyle.SaveViewState ();
854
855                         if (titleStyle != null)
856                                 states [6] = titleStyle.SaveViewState ();
857
858                         if (todayDayStyle != null)
859                                 states [7] =todayDayStyle.SaveViewState ();
860
861                         if (selectorStyle != null)
862                                 states [8] = selectorStyle.SaveViewState ();
863
864                         if (weekendDayStyle != null)
865                                 states [9] = weekendDayStyle.SaveViewState ();
866
867                         if (SelectedDates.Count > 0) {
868                                 ViewState ["SelectedDates"] = dateList;
869                         }
870
871                         states [0] = base.SaveViewState ();
872
873                         for (int i = 0; i < states.Length; i++) {
874                                 if (states [i] != null) {
875                                         return states;
876                                 }
877                         }
878
879                         return null;
880                 }
881
882                 protected override void TrackViewState ()
883                 {
884                         base.TrackViewState ();
885
886                         if (dayHeaderStyle != null)
887                                 dayHeaderStyle.TrackViewState ();
888
889                         if (dayStyle != null)
890                                 dayStyle.TrackViewState ();
891
892                         if (nextPrevStyle != null)
893                                 nextPrevStyle.TrackViewState ();
894
895                         if (otherMonthDayStyle != null)
896                                 otherMonthDayStyle.TrackViewState ();
897
898                         if (selectedDayStyle != null)
899                                 selectedDayStyle.TrackViewState ();
900
901                         if (titleStyle != null)
902                                 titleStyle.TrackViewState ();
903
904                         if (todayDayStyle  != null)
905                                 todayDayStyle.TrackViewState ();
906
907                         if (selectorStyle != null)
908                                 selectorStyle.TrackViewState ();
909
910                         if (weekendDayStyle != null)
911                                 weekendDayStyle.TrackViewState ();
912                 }
913
914                 //
915                 // Private methods
916                 //
917                 void WriteDayHeader (HtmlTextWriter writer)
918                 {
919                         int i, first;
920                         string dayName;
921                         i = first = (int) (DisplayFirstDayOfWeek);
922                         TableCell cell;
923
924
925                         writer.RenderBeginTag (HtmlTextWriterTag.Tr);
926
927                         if (SelectionMode == CalendarSelectionMode.DayWeek) {
928                                 cell = new TableCell();
929                                 cell.HorizontalAlign = HorizontalAlign.Center;
930                                 cell.ApplyStyle (DayHeaderStyle);
931
932                                 // Empty Cell
933                                 cell.RenderBeginTag (writer);
934                                 cell.RenderEndTag (writer);
935                         } else {
936                                 if (SelectionMode == CalendarSelectionMode.DayWeekMonth) {
937                                         TableCell selector = new TableCell ();
938                                         selector.ApplyStyle (SelectorStyle);
939                                         selector.HorizontalAlign = HorizontalAlign.Center;
940
941                                         DateTime date = new DateTime (DisplayDate.Year, DisplayDate.Month, 1); // first date
942                                         int days =  DateTime.DaysInMonth (DisplayDate.Year, DisplayDate.Month);
943
944                                         selector.RenderBeginTag (writer);
945                                         writer.Write (BuildLink ("R" + GetDaysFromZenith (date) + days, SelectMonthText, DayHeaderStyle.ForeColor, Enabled));
946                                         selector.RenderEndTag (writer);
947                                 }
948                         }
949
950                         DateTimeFormatInfo dti = DateInfo;
951                         while (true) {
952                                 DayOfWeek dayOfWeek = (DayOfWeek) i;
953                                 dayName = dti.GetDayName (dayOfWeek);
954
955 #if NET_2_0
956                                 if (UseAccessibleHeader) {
957                                         writer.AddAttribute (HtmlTextWriterAttribute.Abbr, dayName);
958                                         writer.AddAttribute (HtmlTextWriterAttribute.Scope, "col", false);
959                                         cell = new TableHeaderCell();
960                                 }
961                                 else
962 #endif
963                                         cell = new TableCell();
964
965                                 cell.HorizontalAlign = HorizontalAlign.Center;
966                                 cell.ApplyStyle (DayHeaderStyle);
967
968                                 cell.RenderBeginTag (writer);
969
970                                 switch (DayNameFormat) {
971                                 case DayNameFormat.FirstLetter:
972                                         dayName = dayName.Substring (0, 1);
973                                         break;
974                                 case DayNameFormat.FirstTwoLetters:
975                                         dayName = dayName.Substring (0, 2);
976                                         break;
977 #if NET_2_0
978                                 case DayNameFormat.Shortest:
979                                         dayName = dti.GetShortestDayName (dayOfWeek);
980                                         break;
981 #endif
982                                 case DayNameFormat.Full:
983                                         break;
984                                 case DayNameFormat.Short:
985                                 default:
986                                         dayName = dti.GetAbbreviatedDayName (dayOfWeek);
987                                         break;
988                                 }
989
990                                 writer.Write (dayName);
991                                 cell.RenderEndTag (writer);
992
993                                 if (i >= daysInAWeek - 1) {
994                                         i = 0;
995                                 }
996                                 else {
997                                         i++;
998                                 }
999                                 if (i == first)
1000                                         break;
1001                         }
1002
1003                         writer.RenderEndTag ();
1004                 }
1005
1006                 void WriteDay (DateTime date, HtmlTextWriter writer)
1007                 {                       
1008                         TableItemStyle style = new TableItemStyle ();
1009                         TableCell cell = new TableCell ();
1010
1011                         CalendarDay day = new CalendarDay (date,
1012                                 IsWeekEnd (date.DayOfWeek),
1013                                 date == TodaysDate, SelectedDates.Contains (date),
1014                                 GetGlobalCalendar ().GetMonth (DisplayDate) != GetGlobalCalendar ().GetMonth (date),
1015                                 date.Day.ToString ());
1016
1017                         day.IsSelectable = SelectionMode != CalendarSelectionMode.None;
1018                         cell.HorizontalAlign = HorizontalAlign.Center;
1019                         cell.Width = Unit.Percentage (GetCellWidth ());
1020
1021                         LiteralControl lit = new LiteralControl (day.DayNumberText);
1022                         cell.Controls.Add (lit);
1023
1024                         OnDayRender (cell, day);
1025                                         
1026                         if (dayStyle != null && !dayStyle.IsEmpty) {
1027                                 style.CopyFrom (dayStyle);
1028                         }
1029
1030                         if (day.IsWeekend && weekendDayStyle != null && !weekendDayStyle.IsEmpty) {
1031                                 style.CopyFrom (weekendDayStyle);
1032                         }
1033
1034                         if (day.IsToday && todayDayStyle != null && !todayDayStyle.IsEmpty) {
1035                                 style.CopyFrom (todayDayStyle);
1036                         }
1037
1038                         if (day.IsOtherMonth && otherMonthDayStyle != null && !otherMonthDayStyle.IsEmpty) {
1039                                 style.CopyFrom (otherMonthDayStyle);
1040                         }
1041
1042                         if (day.IsSelected && Enabled) {
1043                                 style.BackColor = Color.Silver;
1044                                 style.ForeColor = Color.White;
1045                                 if (selectedDayStyle != null && !selectedDayStyle.IsEmpty) {
1046                                         style.CopyFrom (selectedDayStyle);
1047                                 }
1048                         }
1049
1050                         cell.ApplyStyle (style);
1051
1052                         lit.Text = BuildLink (GetDaysFromZenith (date).ToString (), day.DayNumberText,
1053                                               cell.ForeColor, day.IsSelectable && Enabled);
1054
1055                         cell.RenderControl (writer);
1056                 }
1057
1058                 void WriteDays (HtmlTextWriter writer)
1059                 {
1060                         DateTime date = new DateTime (DisplayDate.Year, DisplayDate.Month, 1); // first date
1061                         DateTime lastDate;
1062                         TableCell selectorCell = null;
1063                         int n;
1064
1065                         // Goes backwards until we find the date of that is begining of the week
1066                         for (n = 0; n < daysInAWeek; n++) {
1067                                 if (date.DayOfWeek == DisplayFirstDayOfWeek)
1068                                         break;
1069
1070                                 date = GetGlobalCalendar().AddDays (date, -1);
1071                         }
1072                         /* if the start date is the first day of the week, we need to shift backward one more week */
1073                         if (n == 0)
1074                                 date = GetGlobalCalendar().AddDays (date, -1 * daysInAWeek);
1075
1076                         lastDate = GetGlobalCalendar().AddDays (date, 6 * daysInAWeek); // Always six weeks per months
1077
1078                         while (true) {
1079                                 writer.RenderBeginTag (HtmlTextWriterTag.Tr);
1080
1081                                 if (HasWeekSelectors (SelectionMode)) { // Week selector
1082                                         if (selectorCell == null) {
1083                                                 selectorCell = new TableCell ();
1084                                                 selectorCell.ApplyStyle (SelectorStyle);
1085                                                 selectorCell.HorizontalAlign = HorizontalAlign.Center;
1086                                                 selectorCell.Width = Unit.Percentage (GetCellWidth ());
1087                                         }
1088
1089                                         selectorCell.RenderBeginTag (writer);
1090                                         writer.Write (BuildLink ("R" + GetDaysFromZenith (date) + "07", SelectWeekText, selectorCell.ForeColor, Enabled));
1091                                         selectorCell.RenderEndTag (writer);
1092                                 }
1093
1094                                 for (int i = 0; i < daysInAWeek; i++) {
1095                                         WriteDay (date, writer);
1096                                         date = GetGlobalCalendar().AddDays (date, 1);
1097                                 }
1098
1099                                 writer.RenderEndTag ();
1100                                 if (date >= lastDate)
1101                                         break;
1102                         }
1103                 }
1104
1105                 string BuildLink (string arg, string text, Color foreColor, bool hasLink)
1106                 {
1107                         StringBuilder str = new StringBuilder ();
1108                         Color clr;
1109                         hasLink = (Page != null && hasLink == true) ? true : false;
1110
1111                         if (hasLink) {
1112                                 str.Append ("<a href=\"");
1113 #if NET_2_0
1114                                 str.Append (Page.ClientScript.GetPostBackClientHyperlink (this, arg, true));
1115 #else
1116                                 str.Append (Page.ClientScript.GetPostBackClientHyperlink (this, arg));
1117 #endif                  
1118                                 str.Append ('\"');
1119                         
1120
1121                                 if (!foreColor.IsEmpty) {
1122                                         clr = foreColor;
1123                                 } else {
1124                                         if (ForeColor.IsEmpty)
1125                                                 clr = Color.Black;
1126                                         else
1127                                                 clr = ForeColor;
1128                                 }
1129
1130                                 str.Append (" style=\"color:" + ColorTranslator.ToHtml (clr));
1131                                 str.Append ("\">");
1132                                 str.Append (text);
1133                                 str.Append ("</a>");
1134                         }
1135                         else 
1136                                 str.Append (text);
1137
1138                         return str.ToString ();
1139                 }
1140
1141                 int GetDaysFromZenith (DateTime date)
1142                 {
1143                         TimeSpan span =  date.Subtract (dateZenith);
1144                         return span.Days;
1145                 }
1146
1147 #if NET_2_0
1148                 void WriteCaption (HtmlTextWriter writer)
1149                 {
1150                         if (CaptionAlign != TableCaptionAlign.NotSet)
1151                                 writer.AddAttribute (HtmlTextWriterAttribute.Align, CaptionAlign.ToString (Helpers.InvariantCulture));
1152
1153                         writer.RenderBeginTag (HtmlTextWriterTag.Caption);
1154                         writer.Write (Caption);
1155                         writer.RenderEndTag ();
1156                 }
1157 #endif
1158
1159                 void WriteTitle (HtmlTextWriter writer)
1160                 {
1161                         TableCell cellNextPrev = null;
1162                         TableCell titleCell = new TableCell ();
1163                         Table tableTitle = new Table ();
1164
1165                         writer.RenderBeginTag (HtmlTextWriterTag.Tr);
1166
1167                         titleCell.ColumnSpan = HasWeekSelectors (SelectionMode) ? 8 : 7;
1168
1169                         if (titleStyle != null && !titleStyle.IsEmpty && !titleStyle.BackColor.IsEmpty) {
1170                                 titleCell.BackColor = titleStyle.BackColor;
1171                         } else {
1172                                 titleCell.BackColor = Color.Silver;
1173                         }
1174
1175                         titleCell.RenderBeginTag (writer);
1176
1177                         // Table
1178                         tableTitle.Width =  Unit.Percentage (100);
1179                         if (titleStyle != null && !titleStyle.IsEmpty) {
1180                                 tableTitle.ApplyStyle (titleStyle);
1181                         }
1182
1183                         tableTitle.RenderBeginTag (writer);
1184                         writer.RenderBeginTag (HtmlTextWriterTag.Tr);
1185
1186                         if (ShowNextPrevMonth) { // Previous Table Data
1187                                 cellNextPrev = new TableCell ();
1188                                 cellNextPrev.ApplyStyle (nextPrevStyle);
1189                                 cellNextPrev.Width = Unit.Percentage (15);
1190
1191                                 DateTime date = GetGlobalCalendar().AddMonths (DisplayDate, - 1);
1192                                 date = GetGlobalCalendar ().AddDays (date, -date.Day + 1);
1193                                 cellNextPrev.RenderBeginTag (writer);
1194                                 writer.Write (BuildLink ("V" + GetDaysFromZenith (date), GetNextPrevFormatText (date, false), cellNextPrev.ForeColor, Enabled));
1195                                 cellNextPrev.RenderEndTag (writer);
1196                         }
1197
1198                         // Current Month Table Data
1199                         {
1200                                 DateTimeFormatInfo dti = DateInfo;
1201                                 string str;
1202                                 TableCell cellMonth = new TableCell ();
1203                                 cellMonth.Width = Unit.Percentage (70);
1204                                 cellMonth.HorizontalAlign = HorizontalAlign.Center;
1205
1206                                 cellMonth.RenderBeginTag (writer);
1207
1208                                 if (TitleFormat == TitleFormat.MonthYear)
1209                                         str = DisplayDate.ToString (dti.YearMonthPattern, dti);
1210                                 else
1211                                         str = dti.GetMonthName (GetGlobalCalendar ().GetMonth (DisplayDate));
1212
1213                                 writer.Write (str);
1214                                 cellMonth.RenderEndTag (writer);
1215                         }
1216
1217                         if (ShowNextPrevMonth) { // Next Table Data
1218                                 DateTime date = GetGlobalCalendar().AddMonths (DisplayDate, + 1);
1219                                 date = GetGlobalCalendar ().AddDays (date, -date.Day + 1);
1220
1221                                 cellNextPrev.HorizontalAlign = HorizontalAlign.Right;
1222                                 cellNextPrev.RenderBeginTag (writer);
1223                                 writer.Write (BuildLink ("V" + GetDaysFromZenith (date), GetNextPrevFormatText (date, true), cellNextPrev.ForeColor, Enabled));
1224                                 cellNextPrev.RenderEndTag (writer);
1225                         }
1226
1227                         writer.RenderEndTag ();
1228                         tableTitle.RenderEndTag (writer);
1229                         titleCell.RenderEndTag (writer);
1230                         writer.RenderEndTag (); //tr
1231
1232                 }
1233
1234
1235                 string GetNextPrevFormatText (DateTime date, bool next)
1236                 {
1237                         string text;
1238                         DateTimeFormatInfo dti = DateInfo;
1239                         switch (NextPrevFormat) {
1240                                 case NextPrevFormat.FullMonth:
1241                                         text = dti.GetMonthName (GetGlobalCalendar ().GetMonth (date));
1242                                         break;
1243                                 case NextPrevFormat.ShortMonth:
1244                                         text = dti.GetAbbreviatedMonthName (GetGlobalCalendar ().GetMonth (date));
1245                                         break;
1246                                 case NextPrevFormat.CustomText:
1247                                 default:
1248                                         text = ((next) ? NextMonthText : PrevMonthText);
1249                                         break;
1250                         }
1251
1252                         return text;
1253                 }
1254
1255                 bool IsWeekEnd (DayOfWeek day)
1256                 {
1257                         return (day == DayOfWeek.Saturday || day == DayOfWeek.Sunday);
1258                 }
1259
1260                 double GetCellWidth ()
1261                 {
1262                         return HasWeekSelectors (SelectionMode) ? 100/8 : 100/7;
1263                 }
1264
1265                 System.Globalization.Calendar GetGlobalCalendar ()
1266                 {
1267                         return DateTimeFormatInfo.CurrentInfo.Calendar;
1268                 }
1269
1270                 [WebSysDescription ("")]
1271                 [WebCategory ("Action")]
1272                 public event DayRenderEventHandler DayRender {
1273                         add {
1274                                 Events.AddHandler (DayRenderEvent, value);
1275                         }
1276                         remove {
1277                                 Events.RemoveHandler (DayRenderEvent, value);
1278                         }
1279                 }
1280
1281                 [WebSysDescription ("")]
1282                 [WebCategory ("Action")]
1283                 public event EventHandler SelectionChanged {
1284                         add {
1285                                 Events.AddHandler (SelectionChangedEvent, value);
1286                         }
1287                         remove {
1288                                 Events.RemoveHandler (SelectionChangedEvent, value);
1289                         }
1290                 }
1291
1292                 [WebSysDescription ("")]
1293                 [WebCategory ("Action")]
1294                 public event MonthChangedEventHandler VisibleMonthChanged {
1295                         add {
1296                                 Events.AddHandler (VisibleMonthChangedEvent, value);
1297                         }
1298                         remove {
1299                                 Events.RemoveHandler (VisibleMonthChangedEvent, value);
1300                         }
1301                 }
1302         }
1303 }
1304