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