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