2016-08-03 10:59:49 +00:00
//------------------------------------------------------------------------------
// <copyright file="Calendar.cs" company="Microsoft">
// Copyright (c) Microsoft Corporation. All rights reserved.
// </copyright>
//------------------------------------------------------------------------------
namespace System.Web.UI.WebControls {
using System.Threading ;
using System.Globalization ;
using System.ComponentModel ;
using System ;
using System.Web ;
using System.Web.UI ;
using System.Web.Util ;
using System.Collections ;
using System.ComponentModel.Design ;
using System.Drawing ;
using System.Text ;
using System.IO ;
using System.Reflection ;
/// <devdoc>
/// <para>Displays a one-month calendar and allows the user to
/// view and select a specific day, week, or month.</para>
/// </devdoc>
[
ControlValueProperty ( "SelectedDate" , typeof ( DateTime ) , "1/1/0001" ) ,
DataBindingHandler ( "System.Web.UI.Design.WebControls.CalendarDataBindingHandler, " + AssemblyRef . SystemDesign ) ,
DefaultEvent ( "SelectionChanged" ) ,
DefaultProperty ( "SelectedDate" ) ,
Designer ( "System.Web.UI.Design.WebControls.CalendarDesigner, " + AssemblyRef . SystemDesign ) ,
SupportsEventValidation
]
public class Calendar : WebControl , IPostBackEventHandler {
private static readonly object EventDayRender = new object ( ) ;
private static readonly object EventSelectionChanged = new object ( ) ;
private static readonly object EventVisibleMonthChanged = new object ( ) ;
private TableItemStyle titleStyle ;
private TableItemStyle nextPrevStyle ;
private TableItemStyle dayHeaderStyle ;
private TableItemStyle selectorStyle ;
private TableItemStyle dayStyle ;
private TableItemStyle otherMonthDayStyle ;
private TableItemStyle todayDayStyle ;
private TableItemStyle selectedDayStyle ;
private TableItemStyle weekendDayStyle ;
private string defaultButtonColorText ;
private static readonly Color DefaultForeColor = Color . Black ;
private Color defaultForeColor ;
private ArrayList dateList ;
private SelectedDatesCollection selectedDates ;
2016-11-10 13:04:39 +00:00
private System . Globalization . Calendar threadCalendar ;
2016-08-03 10:59:49 +00:00
private DateTime minSupportedDate ;
private DateTime maxSupportedDate ;
#if DEBUG
private bool threadCalendarInitialized ;
#endif
private const string SELECT_RANGE_COMMAND = "R" ;
private const string NAVIGATE_MONTH_COMMAND = "V" ;
private static DateTime baseDate = new DateTime ( 2000 , 1 , 1 ) ;
private const int STYLEMASK_DAY = 16 ;
private const int STYLEMASK_UNIQUE = 15 ;
private const int STYLEMASK_SELECTED = 8 ;
private const int STYLEMASK_TODAY = 4 ;
private const int STYLEMASK_OTHERMONTH = 2 ;
private const int STYLEMASK_WEEKEND = 1 ;
private const string ROWBEGINTAG = "<tr>" ;
private const string ROWENDTAG = "</tr>" ;
// Cache commonly used strings. This improves performance and memory usage.
private const int cachedNumberMax = 31 ;
private static readonly string [ ] cachedNumbers = new string [ ] {
"0" , "1" , "2" , "3" , "4" , "5" , "6" ,
"7" , "8" , "9" , "10" , "11" , "12" , "13" ,
"14" , "15" , "16" , "17" , "18" , "19" , "20" ,
"21" , "22" , "23" , "24" , "25" , "26" , "27" ,
"28" , "29" , "30" , "31" ,
} ;
/// <devdoc>
/// <para>Initializes a new instance of the <see cref='System.Web.UI.WebControls.Calendar'/> class.</para>
/// </devdoc>
public Calendar ( ) : base ( HtmlTextWriterTag . Table ) {
}
[
Localizable ( true ) ,
DefaultValue ( "" ) ,
WebCategory ( "Accessibility" ) ,
WebSysDescription ( SR . Calendar_Caption )
]
public virtual string Caption {
get {
string s = ( string ) ViewState [ "Caption" ] ;
return ( s ! = null ) ? s : String . Empty ;
}
set {
ViewState [ "Caption" ] = value ;
}
}
[
DefaultValue ( TableCaptionAlign . NotSet ) ,
WebCategory ( "Accessibility" ) ,
WebSysDescription ( SR . WebControl_CaptionAlign )
]
public virtual TableCaptionAlign CaptionAlign {
get {
object o = ViewState [ "CaptionAlign" ] ;
return ( o ! = null ) ? ( TableCaptionAlign ) o : TableCaptionAlign . NotSet ;
}
set {
if ( ( value < TableCaptionAlign . NotSet ) | |
( value > TableCaptionAlign . Right ) ) {
throw new ArgumentOutOfRangeException ( "value" ) ;
}
ViewState [ "CaptionAlign" ] = value ;
}
}
/// <devdoc>
/// <para>Gets or sets the amount of space between cells.</para>
/// </devdoc>
[
WebCategory ( "Layout" ) ,
DefaultValue ( 2 ) ,
WebSysDescription ( SR . Calendar_CellPadding )
]
public int CellPadding {
get {
object o = ViewState [ "CellPadding" ] ;
return ( ( o = = null ) ? 2 : ( int ) o ) ;
}
set {
if ( value < - 1 ) {
throw new ArgumentOutOfRangeException ( "value" ) ;
}
ViewState [ "CellPadding" ] = value ;
}
}
/// <devdoc>
/// <para>Gets or sets the amount of space between the contents of a cell
/// and the cell's border.</para>
/// </devdoc>
[
WebCategory ( "Layout" ) ,
DefaultValue ( 0 ) ,
WebSysDescription ( SR . Calendar_CellSpacing )
]
public int CellSpacing {
get {
object o = ViewState [ "CellSpacing" ] ;
return ( ( o = = null ) ? 0 : ( int ) o ) ;
}
set {
if ( value < - 1 ) {
throw new ArgumentOutOfRangeException ( "value" ) ;
}
ViewState [ "CellSpacing" ] = ( int ) value ;
}
}
/// <devdoc>
/// <para> Gets the style property of the day-of-the-week header. This property is read-only.</para>
/// </devdoc>
[
WebCategory ( "Styles" ) ,
WebSysDescription ( SR . Calendar_DayHeaderStyle ) ,
DesignerSerializationVisibility ( DesignerSerializationVisibility . Content ) ,
NotifyParentProperty ( true ) ,
PersistenceMode ( PersistenceMode . InnerProperty )
]
public TableItemStyle DayHeaderStyle {
get {
if ( dayHeaderStyle = = null ) {
dayHeaderStyle = new TableItemStyle ( ) ;
if ( IsTrackingViewState )
( ( IStateManager ) dayHeaderStyle ) . TrackViewState ( ) ;
}
return dayHeaderStyle ;
}
}
/// <devdoc>
/// <para>Gets or sets
/// the format for the names of days.</para>
/// </devdoc>
[
WebCategory ( "Appearance" ) ,
DefaultValue ( DayNameFormat . Short ) ,
WebSysDescription ( SR . Calendar_DayNameFormat )
]
public DayNameFormat DayNameFormat {
get {
object dnf = ViewState [ "DayNameFormat" ] ;
return ( ( dnf = = null ) ? DayNameFormat . Short : ( DayNameFormat ) dnf ) ;
}
set {
if ( value < DayNameFormat . Full | | value > DayNameFormat . Shortest ) {
throw new ArgumentOutOfRangeException ( "value" ) ;
}
ViewState [ "DayNameFormat" ] = value ;
}
}
/// <devdoc>
/// <para> Gets the style properties for the days. This property is read-only.</para>
/// </devdoc>
[
WebCategory ( "Styles" ) ,
DefaultValue ( null ) ,
WebSysDescription ( SR . Calendar_DayStyle ) ,
DesignerSerializationVisibility ( DesignerSerializationVisibility . Content ) ,
NotifyParentProperty ( true ) ,
PersistenceMode ( PersistenceMode . InnerProperty )
]
public TableItemStyle DayStyle {
get {
if ( dayStyle = = null ) {
dayStyle = new TableItemStyle ( ) ;
if ( IsTrackingViewState )
( ( IStateManager ) dayStyle ) . TrackViewState ( ) ;
}
return dayStyle ;
}
}
/// <devdoc>
/// <para> Gets
/// or sets the day of the week to display in the calendar's first
/// column.</para>
/// </devdoc>
[
WebCategory ( "Appearance" ) ,
DefaultValue ( FirstDayOfWeek . Default ) ,
WebSysDescription ( SR . Calendar_FirstDayOfWeek )
]
public FirstDayOfWeek FirstDayOfWeek {
get {
object o = ViewState [ "FirstDayOfWeek" ] ;
return ( ( o = = null ) ? FirstDayOfWeek . Default : ( FirstDayOfWeek ) o ) ;
}
set {
if ( value < FirstDayOfWeek . Sunday | | value > FirstDayOfWeek . Default ) {
throw new ArgumentOutOfRangeException ( "value" ) ;
}
ViewState [ "FirstDayOfWeek" ] = value ;
}
}
/// <devdoc>
/// <para>Gets or sets the text shown for the next month
/// navigation hyperlink if the <see cref='System.Web.UI.WebControls.Calendar.ShowNextPrevMonth'/> property is set to
/// <see langword='true'/>.</para>
/// </devdoc>
[
Localizable ( true ) ,
WebCategory ( "Appearance" ) ,
DefaultValue ( ">" ) ,
WebSysDescription ( SR . Calendar_NextMonthText )
]
public string NextMonthText {
get {
object s = ViewState [ "NextMonthText" ] ;
return ( ( s = = null ) ? ">" : ( String ) s ) ;
}
set {
ViewState [ "NextMonthText" ] = value ;
}
}
/// <devdoc>
/// <para>Gets or sets the format of the next and previous month hyperlinks in the
/// title.</para>
/// </devdoc>
[
WebCategory ( "Appearance" ) ,
DefaultValue ( NextPrevFormat . CustomText ) ,
WebSysDescription ( SR . Calendar_NextPrevFormat )
]
public NextPrevFormat NextPrevFormat {
get {
object npf = ViewState [ "NextPrevFormat" ] ;
return ( ( npf = = null ) ? NextPrevFormat . CustomText : ( NextPrevFormat ) npf ) ;
}
set {
if ( value < NextPrevFormat . CustomText | | value > NextPrevFormat . FullMonth ) {
throw new ArgumentOutOfRangeException ( "value" ) ;
}
ViewState [ "NextPrevFormat" ] = value ;
}
}
/// <devdoc>
/// <para> Gets the style properties for the next/previous month navigators. This property is
/// read-only.</para>
/// </devdoc>
[
WebCategory ( "Styles" ) ,
WebSysDescription ( SR . Calendar_NextPrevStyle ) ,
DesignerSerializationVisibility ( DesignerSerializationVisibility . Content ) ,
NotifyParentProperty ( true ) ,
PersistenceMode ( PersistenceMode . InnerProperty )
]
public TableItemStyle NextPrevStyle {
get {
if ( nextPrevStyle = = null ) {
nextPrevStyle = new TableItemStyle ( ) ;
if ( IsTrackingViewState )
( ( IStateManager ) nextPrevStyle ) . TrackViewState ( ) ;
}
return nextPrevStyle ;
}
}
/// <devdoc>
/// <para>Gets the style properties for the days from the months preceding and following the current month.
/// This property is read-only.</para>
/// </devdoc>
[
WebCategory ( "Styles" ) ,
DefaultValue ( null ) ,
WebSysDescription ( SR . Calendar_OtherMonthDayStyle ) ,
DesignerSerializationVisibility ( DesignerSerializationVisibility . Content ) ,
NotifyParentProperty ( true ) ,
PersistenceMode ( PersistenceMode . InnerProperty )
]
public TableItemStyle OtherMonthDayStyle {
get {
if ( otherMonthDayStyle = = null ) {
otherMonthDayStyle = new TableItemStyle ( ) ;
if ( IsTrackingViewState )
( ( IStateManager ) otherMonthDayStyle ) . TrackViewState ( ) ;
}
return otherMonthDayStyle ;
}
}
/// <devdoc>
/// <para>Gets or sets the text shown for the previous month
/// navigation hyperlink if the <see cref='System.Web.UI.WebControls.Calendar.ShowNextPrevMonth'/> property is set to
/// <see langword='true'/>
/// .</para>
/// </devdoc>
[
Localizable ( true ) ,
WebCategory ( "Appearance" ) ,
DefaultValue ( "<" ) ,
WebSysDescription ( SR . Calendar_PrevMonthText )
]
public string PrevMonthText {
get {
object s = ViewState [ "PrevMonthText" ] ;
return ( ( s = = null ) ? "<" : ( String ) s ) ;
}
set {
ViewState [ "PrevMonthText" ] = value ;
}
}
public override bool SupportsDisabledAttribute {
get {
return RenderingCompatibility < VersionUtil . Framework40 ;
}
}
/// <devdoc>
/// <para>Gets or sets the date that is currently selected
/// date.</para>
/// </devdoc>
[
Bindable ( true , BindingDirection . TwoWay ) ,
DefaultValue ( typeof ( DateTime ) , "1/1/0001" ) ,
WebSysDescription ( SR . Calendar_SelectedDate )
]
public DateTime SelectedDate {
get {
if ( SelectedDates . Count = = 0 ) {
return DateTime . MinValue ;
}
return SelectedDates [ 0 ] ;
}
set {
if ( value = = DateTime . MinValue ) {
SelectedDates . Clear ( ) ;
}
else {
SelectedDates . SelectRange ( value , value ) ;
}
}
}
/// <devdoc>
/// <para>Gets a collection of <see cref='System.DateTime' qualify='true'/> objects representing days selected on the <see cref='System.Web.UI.WebControls.Calendar'/>. This
/// property is read-only.</para>
/// </devdoc>
[
Browsable ( false ) ,
WebSysDescription ( SR . Calendar_SelectedDates ) ,
DesignerSerializationVisibility ( DesignerSerializationVisibility . Hidden )
]
public SelectedDatesCollection SelectedDates {
get {
if ( selectedDates = = null ) {
if ( dateList = = null ) {
dateList = new ArrayList ( ) ;
}
selectedDates = new SelectedDatesCollection ( dateList ) ;
}
return selectedDates ;
}
}
/// <devdoc>
/// <para>Gets the style properties for the selected date. This property is read-only.</para>
/// </devdoc>
[
WebCategory ( "Styles" ) ,
DefaultValue ( null ) ,
WebSysDescription ( SR . Calendar_SelectedDayStyle ) ,
DesignerSerializationVisibility ( DesignerSerializationVisibility . Content ) ,
NotifyParentProperty ( true ) ,
PersistenceMode ( PersistenceMode . InnerProperty )
]
public TableItemStyle SelectedDayStyle {
get {
if ( selectedDayStyle = = null ) {
selectedDayStyle = new TableItemStyle ( ) ;
if ( IsTrackingViewState )
( ( IStateManager ) selectedDayStyle ) . TrackViewState ( ) ;
}
return selectedDayStyle ;
}
}
/// <devdoc>
/// <para>Gets or sets the date selection capabilities on the
/// <see cref='System.Web.UI.WebControls.Calendar'/>
/// to allow the user to select a day, week, or month.</para>
/// </devdoc>
[
WebCategory ( "Behavior" ) ,
DefaultValue ( CalendarSelectionMode . Day ) ,
WebSysDescription ( SR . Calendar_SelectionMode )
]
public CalendarSelectionMode SelectionMode {
get {
object csm = ViewState [ "SelectionMode" ] ;
return ( ( csm = = null ) ? CalendarSelectionMode . Day : ( CalendarSelectionMode ) csm ) ;
}
set {
if ( value < CalendarSelectionMode . None | | value > CalendarSelectionMode . DayWeekMonth ) {
throw new ArgumentOutOfRangeException ( "value" ) ;
}
ViewState [ "SelectionMode" ] = value ;
}
}
/// <devdoc>
/// <para>Gets or sets the text shown for the month selection in
/// the selector column if <see cref='System.Web.UI.WebControls.Calendar.SelectionMode'/> is
/// <see langword='CalendarSelectionMode.DayWeekMonth'/>.</para>
/// </devdoc>
[
Localizable ( true ) ,
WebCategory ( "Appearance" ) ,
DefaultValue ( ">>" ) ,
WebSysDescription ( SR . Calendar_SelectMonthText )
]
public string SelectMonthText {
get {
object s = ViewState [ "SelectMonthText" ] ;
return ( ( s = = null ) ? ">>" : ( String ) s ) ;
}
set {
ViewState [ "SelectMonthText" ] = value ;
}
}
/// <devdoc>
/// <para> Gets the style properties for the week and month selectors. This property is read-only.</para>
/// </devdoc>
[
WebCategory ( "Styles" ) ,
WebSysDescription ( SR . Calendar_SelectorStyle ) ,
DesignerSerializationVisibility ( DesignerSerializationVisibility . Content ) ,
NotifyParentProperty ( true ) ,
PersistenceMode ( PersistenceMode . InnerProperty )
]
public TableItemStyle SelectorStyle {
get {
if ( selectorStyle = = null ) {
selectorStyle = new TableItemStyle ( ) ;
if ( IsTrackingViewState )
( ( IStateManager ) selectorStyle ) . TrackViewState ( ) ;
}
return selectorStyle ;
}
}
/// <devdoc>
/// <para>Gets or sets the text shown for the week selection in
/// the selector column if <see cref='System.Web.UI.WebControls.Calendar.SelectionMode'/> is
/// <see langword='CalendarSelectionMode.DayWeek '/>or
/// <see langword='CalendarSelectionMode.DayWeekMonth'/>.</para>
/// </devdoc>
[
Localizable ( true ) ,
WebCategory ( "Appearance" ) ,
DefaultValue ( ">" ) ,
WebSysDescription ( SR . Calendar_SelectWeekText )
]
public string SelectWeekText {
get {
object s = ViewState [ "SelectWeekText" ] ;
return ( ( s = = null ) ? ">" : ( String ) s ) ;
}
set {
ViewState [ "SelectWeekText" ] = value ;
}
}
/// <devdoc>
/// <para>Gets or sets
/// a value indicating whether the days of the week are displayed.</para>
/// </devdoc>
[
WebCategory ( "Appearance" ) ,
DefaultValue ( true ) ,
WebSysDescription ( SR . Calendar_ShowDayHeader )
]
public bool ShowDayHeader {
get {
object b = ViewState [ "ShowDayHeader" ] ;
return ( ( b = = null ) ? true : ( bool ) b ) ;
}
set {
ViewState [ "ShowDayHeader" ] = value ;
}
}
/// <devdoc>
/// <para>Gets or set
/// a value indicating whether days on the calendar are displayed with a border.</para>
/// </devdoc>
[
WebCategory ( "Appearance" ) ,
DefaultValue ( false ) ,
WebSysDescription ( SR . Calendar_ShowGridLines )
]
public bool ShowGridLines {
get {
object b = ViewState [ "ShowGridLines" ] ;
return ( ( b = = null ) ? false : ( bool ) b ) ;
}
set {
ViewState [ "ShowGridLines" ] = value ;
}
}
/// <devdoc>
/// <para>Gets or sets a value indicating whether the <see cref='System.Web.UI.WebControls.Calendar'/>
/// displays the next and pervious month
/// hyperlinks in the title.</para>
/// </devdoc>
[
WebCategory ( "Appearance" ) ,
DefaultValue ( true ) ,
WebSysDescription ( SR . Calendar_ShowNextPrevMonth )
]
public bool ShowNextPrevMonth {
get {
object b = ViewState [ "ShowNextPrevMonth" ] ;
return ( ( b = = null ) ? true : ( bool ) b ) ;
}
set {
ViewState [ "ShowNextPrevMonth" ] = value ;
}
}
/// <devdoc>
/// <para> Gets or
/// sets a value indicating whether the title is displayed.</para>
/// </devdoc>
[
WebCategory ( "Appearance" ) ,
DefaultValue ( true ) ,
WebSysDescription ( SR . Calendar_ShowTitle )
]
public bool ShowTitle {
get {
object b = ViewState [ "ShowTitle" ] ;
return ( ( b = = null ) ? true : ( bool ) b ) ;
}
set {
ViewState [ "ShowTitle" ] = value ;
}
}
/// <devdoc>
/// <para>Gets or sets how the month name is formatted in the title
/// bar.</para>
/// </devdoc>
[
WebCategory ( "Appearance" ) ,
DefaultValue ( TitleFormat . MonthYear ) ,
WebSysDescription ( SR . Calendar_TitleFormat )
]
public TitleFormat TitleFormat {
get {
object tf = ViewState [ "TitleFormat" ] ;
return ( ( tf = = null ) ? TitleFormat . MonthYear : ( TitleFormat ) tf ) ;
}
set {
if ( value < TitleFormat . Month | | value > TitleFormat . MonthYear ) {
throw new ArgumentOutOfRangeException ( "value" ) ;
}
ViewState [ "TitleFormat" ] = value ;
}
}
/// <devdoc>
/// <para>Gets the style properties of the <see cref='System.Web.UI.WebControls.Calendar'/> title. This property is
/// read-only.</para>
/// </devdoc>
[
WebCategory ( "Styles" ) ,
WebSysDescription ( SR . Calendar_TitleStyle ) ,
DesignerSerializationVisibility ( DesignerSerializationVisibility . Content ) ,
NotifyParentProperty ( true ) ,
PersistenceMode ( PersistenceMode . InnerProperty ) ,
]
public TableItemStyle TitleStyle {
get {
if ( titleStyle = = null ) {
titleStyle = new TableItemStyle ( ) ;
if ( IsTrackingViewState )
( ( IStateManager ) titleStyle ) . TrackViewState ( ) ;
}
return titleStyle ;
}
}
/// <devdoc>
/// <para>Gets the style properties for today's date on the
/// <see cref='System.Web.UI.WebControls.Calendar'/>. This
/// property is read-only.</para>
/// </devdoc>
[
WebCategory ( "Styles" ) ,
DefaultValue ( null ) ,
WebSysDescription ( SR . Calendar_TodayDayStyle ) ,
DesignerSerializationVisibility ( DesignerSerializationVisibility . Content ) ,
NotifyParentProperty ( true ) ,
PersistenceMode ( PersistenceMode . InnerProperty )
]
public TableItemStyle TodayDayStyle {
get {
if ( todayDayStyle = = null ) {
todayDayStyle = new TableItemStyle ( ) ;
if ( IsTrackingViewState )
( ( IStateManager ) todayDayStyle ) . TrackViewState ( ) ;
}
return todayDayStyle ;
}
}
/// <devdoc>
/// <para>Gets or sets the value to use as today's date.</para>
/// </devdoc>
[
Browsable ( false ) ,
WebSysDescription ( SR . Calendar_TodaysDate ) ,
DesignerSerializationVisibility ( DesignerSerializationVisibility . Hidden )
]
public DateTime TodaysDate {
get {
object o = ViewState [ "TodaysDate" ] ;
return ( ( o = = null ) ? DateTime . Today : ( DateTime ) o ) ;
}
set {
ViewState [ "TodaysDate" ] = value . Date ;
}
}
[
DefaultValue ( true ) ,
WebCategory ( "Accessibility" ) ,
WebSysDescription ( SR . Table_UseAccessibleHeader )
]
public virtual bool UseAccessibleHeader {
get {
object o = ViewState [ "UseAccessibleHeader" ] ;
return ( o ! = null ) ? ( bool ) o : true ;
}
set {
ViewState [ "UseAccessibleHeader" ] = value ;
}
}
/// <devdoc>
/// <para>Gets or sets the date that specifies what month to display. The date can be
/// be any date within the month.</para>
/// </devdoc>
[
Bindable ( true ) ,
DefaultValue ( typeof ( DateTime ) , "1/1/0001" ) ,
WebSysDescription ( SR . Calendar_VisibleDate )
]
public DateTime VisibleDate {
get {
object o = ViewState [ "VisibleDate" ] ;
return ( ( o = = null ) ? DateTime . MinValue : ( DateTime ) o ) ;
}
set {
ViewState [ "VisibleDate" ] = value . Date ;
}
}
/// <devdoc>
/// <para>Gets the style properties for the displaying weekend dates. This property is
/// read-only.</para>
/// </devdoc>
[
WebCategory ( "Styles" ) ,
WebSysDescription ( SR . Calendar_WeekendDayStyle ) ,
DesignerSerializationVisibility ( DesignerSerializationVisibility . Content ) ,
NotifyParentProperty ( true ) ,
PersistenceMode ( PersistenceMode . InnerProperty )
]
public TableItemStyle WeekendDayStyle {
get {
if ( weekendDayStyle = = null ) {
weekendDayStyle = new TableItemStyle ( ) ;
if ( IsTrackingViewState )
( ( IStateManager ) weekendDayStyle ) . TrackViewState ( ) ;
}
return weekendDayStyle ;
}
}
/// <devdoc>
/// <para>Occurs when each day is created in teh control hierarchy for the <see cref='System.Web.UI.WebControls.Calendar'/>.</para>
/// </devdoc>
[
WebCategory ( "Action" ) ,
WebSysDescription ( SR . Calendar_OnDayRender )
]
public event DayRenderEventHandler DayRender {
add {
Events . AddHandler ( EventDayRender , value ) ;
}
remove {
Events . RemoveHandler ( EventDayRender , value ) ;
}
}
/// <devdoc>
/// <para>Occurs when the user clicks on a day, week, or month
/// selector and changes the <see cref='System.Web.UI.WebControls.Calendar.SelectedDate'/>.</para>
/// </devdoc>
[
WebCategory ( "Action" ) ,
WebSysDescription ( SR . Calendar_OnSelectionChanged )
]
public event EventHandler SelectionChanged {
add {
Events . AddHandler ( EventSelectionChanged , value ) ;
}
remove {
Events . RemoveHandler ( EventSelectionChanged , value ) ;
}
}
/// <devdoc>
/// <para>Occurs when the
/// user clicks on the next or previous month <see cref='System.Web.UI.WebControls.Button'/> controls on the title.</para>
/// </devdoc>
[
WebCategory ( "Action" ) ,
WebSysDescription ( SR . Calendar_OnVisibleMonthChanged )
]
public event MonthChangedEventHandler VisibleMonthChanged {
add {
Events . AddHandler ( EventVisibleMonthChanged , value ) ;
}
remove {
Events . RemoveHandler ( EventVisibleMonthChanged , value ) ;
}
}
// Methods
/// <devdoc>
/// </devdoc>
private void ApplyTitleStyle ( TableCell titleCell , Table titleTable , TableItemStyle titleStyle ) {
// apply affects that affect the whole background to the cell
if ( titleStyle . BackColor ! = Color . Empty ) {
titleCell . BackColor = titleStyle . BackColor ;
}
if ( titleStyle . BorderColor ! = Color . Empty ) {
titleCell . BorderColor = titleStyle . BorderColor ;
}
if ( titleStyle . BorderWidth ! = Unit . Empty ) {
titleCell . BorderWidth = titleStyle . BorderWidth ;
}
if ( titleStyle . BorderStyle ! = BorderStyle . NotSet ) {
titleCell . BorderStyle = titleStyle . BorderStyle ;
}
if ( titleStyle . Height ! = Unit . Empty ) {
titleCell . Height = titleStyle . Height ;
}
if ( titleStyle . VerticalAlign ! = VerticalAlign . NotSet ) {
titleCell . VerticalAlign = titleStyle . VerticalAlign ;
}
// apply affects that affect everything else to the table
if ( titleStyle . CssClass . Length > 0 ) {
titleTable . CssClass = titleStyle . CssClass ;
}
else if ( CssClass . Length > 0 ) {
titleTable . CssClass = CssClass ;
}
if ( titleStyle . ForeColor ! = Color . Empty ) {
titleTable . ForeColor = titleStyle . ForeColor ;
}
else if ( ForeColor ! = Color . Empty ) {
titleTable . ForeColor = ForeColor ;
}
titleTable . Font . CopyFrom ( titleStyle . Font ) ;
titleTable . Font . MergeWith ( this . Font ) ;
}
/// <internalonly/>
/// <devdoc>
/// </devdoc>
protected override ControlCollection CreateControlCollection ( ) {
return new InternalControlCollection ( this ) ;
}
/// <devdoc>
/// </devdoc>
private DateTime EffectiveVisibleDate ( ) {
DateTime visDate = VisibleDate ;
if ( visDate . Equals ( DateTime . MinValue ) ) {
visDate = TodaysDate ;
}
// VSWhidbey 366243
if ( IsMinSupportedYearMonth ( visDate ) ) {
return minSupportedDate ;
}
else {
return threadCalendar . AddDays ( visDate , - ( threadCalendar . GetDayOfMonth ( visDate ) - 1 ) ) ;
}
}
/// <devdoc>
/// </devdoc>
private DateTime FirstCalendarDay ( DateTime visibleDate ) {
DateTime firstDayOfMonth = visibleDate ;
// VSWhidbey 366243
if ( IsMinSupportedYearMonth ( firstDayOfMonth ) ) {
return firstDayOfMonth ;
}
int daysFromLastMonth = ( ( int ) threadCalendar . GetDayOfWeek ( firstDayOfMonth ) ) - NumericFirstDayOfWeek ( ) ;
// Always display at least one day from the previous month
if ( daysFromLastMonth < = 0 ) {
daysFromLastMonth + = 7 ;
}
return threadCalendar . AddDays ( firstDayOfMonth , - daysFromLastMonth ) ;
}
/// <devdoc>
/// </devdoc>
private string GetCalendarButtonText ( string eventArgument , string buttonText , string title , bool showLink , Color foreColor ) {
if ( showLink ) {
StringBuilder sb = new StringBuilder ( ) ;
sb . Append ( "<a href=\"" ) ;
sb . Append ( Page . ClientScript . GetPostBackClientHyperlink ( this , eventArgument , true ) ) ;
// ForeColor needs to go on the actual link. This breaks the uplevel/downlevel rules a little bit,
// but it is worth doing so the day links do not change color when they go in the history on
// downlevel browsers. Otherwise, people get it confused with the selection mechanism.
sb . Append ( "\" style=\"color:" ) ;
sb . Append ( foreColor . IsEmpty ? defaultButtonColorText : ColorTranslator . ToHtml ( foreColor ) ) ;
if ( ! String . IsNullOrEmpty ( title ) ) {
sb . Append ( "\" title=\"" ) ;
sb . Append ( title ) ;
}
sb . Append ( "\">" ) ;
sb . Append ( buttonText ) ;
sb . Append ( "</a>" ) ;
return sb . ToString ( ) ;
}
else {
return buttonText ;
}
}
/// <devdoc>
/// </devdoc>
private int GetDefinedStyleMask ( ) {
// Selected is always defined because it has default effects
int styleMask = STYLEMASK_SELECTED ;
if ( dayStyle ! = null & & ! dayStyle . IsEmpty )
styleMask | = STYLEMASK_DAY ;
if ( todayDayStyle ! = null & & ! todayDayStyle . IsEmpty )
styleMask | = STYLEMASK_TODAY ;
if ( otherMonthDayStyle ! = null & & ! otherMonthDayStyle . IsEmpty )
styleMask | = STYLEMASK_OTHERMONTH ;
if ( weekendDayStyle ! = null & & ! weekendDayStyle . IsEmpty )
styleMask | = STYLEMASK_WEEKEND ;
return styleMask ;
}
/// <devdoc>
/// </devdoc>
private string GetMonthName ( int m , bool bFull ) {
if ( bFull ) {
return DateTimeFormatInfo . CurrentInfo . GetMonthName ( m ) ;
}
else {
return DateTimeFormatInfo . CurrentInfo . GetAbbreviatedMonthName ( m ) ;
}
}
/// <devdoc>
/// <para>Determines if a <see cref='System.Web.UI.WebControls.CalendarSelectionMode'/>
/// contains week selectors.</para>
/// </devdoc>
protected bool HasWeekSelectors ( CalendarSelectionMode selectionMode ) {
return ( selectionMode = = CalendarSelectionMode . DayWeek
| | selectionMode = = CalendarSelectionMode . DayWeekMonth ) ;
}
private bool IsTheSameYearMonth ( DateTime date1 , DateTime date2 ) {
#if DEBUG
Debug . Assert ( threadCalendarInitialized ) ;
#endif
return ( threadCalendar . GetEra ( date1 ) = = threadCalendar . GetEra ( date2 ) & &
threadCalendar . GetYear ( date1 ) = = threadCalendar . GetYear ( date2 ) & &
threadCalendar . GetMonth ( date1 ) = = threadCalendar . GetMonth ( date2 ) ) ;
}
private bool IsMinSupportedYearMonth ( DateTime date ) {
#if DEBUG
Debug . Assert ( threadCalendarInitialized ) ;
#endif
return IsTheSameYearMonth ( minSupportedDate , date ) ;
}
private bool IsMaxSupportedYearMonth ( DateTime date ) {
#if DEBUG
Debug . Assert ( threadCalendarInitialized ) ;
#endif
return IsTheSameYearMonth ( maxSupportedDate , date ) ;
}
/// <internalonly/>
/// <devdoc>
/// <para>Loads a saved state of the <see cref='System.Web.UI.WebControls.Calendar'/>. </para>
/// </devdoc>
protected override void LoadViewState ( object savedState ) {
if ( savedState ! = null ) {
object [ ] myState = ( object [ ] ) savedState ;
if ( myState [ 0 ] ! = null )
base . LoadViewState ( myState [ 0 ] ) ;
if ( myState [ 1 ] ! = null )
( ( IStateManager ) TitleStyle ) . LoadViewState ( myState [ 1 ] ) ;
if ( myState [ 2 ] ! = null )
( ( IStateManager ) NextPrevStyle ) . LoadViewState ( myState [ 2 ] ) ;
if ( myState [ 3 ] ! = null )
( ( IStateManager ) DayStyle ) . LoadViewState ( myState [ 3 ] ) ;
if ( myState [ 4 ] ! = null )
( ( IStateManager ) DayHeaderStyle ) . LoadViewState ( myState [ 4 ] ) ;
if ( myState [ 5 ] ! = null )
( ( IStateManager ) TodayDayStyle ) . LoadViewState ( myState [ 5 ] ) ;
if ( myState [ 6 ] ! = null )
( ( IStateManager ) WeekendDayStyle ) . LoadViewState ( myState [ 6 ] ) ;
if ( myState [ 7 ] ! = null )
( ( IStateManager ) OtherMonthDayStyle ) . LoadViewState ( myState [ 7 ] ) ;
if ( myState [ 8 ] ! = null )
( ( IStateManager ) SelectedDayStyle ) . LoadViewState ( myState [ 8 ] ) ;
if ( myState [ 9 ] ! = null )
( ( IStateManager ) SelectorStyle ) . LoadViewState ( myState [ 9 ] ) ;
ArrayList selDates = ( ArrayList ) ViewState [ "SD" ] ;
if ( selDates ! = null ) {
dateList = selDates ;
selectedDates = null ; // reset wrapper collection
}
}
}
/// <internalonly/>
/// <devdoc>
/// <para>Marks the starting point to begin tracking and saving changes to the
/// control as part of the control viewstate.</para>
/// </devdoc>
protected override void TrackViewState ( ) {
base . TrackViewState ( ) ;
if ( titleStyle ! = null )
( ( IStateManager ) titleStyle ) . TrackViewState ( ) ;
if ( nextPrevStyle ! = null )
( ( IStateManager ) nextPrevStyle ) . TrackViewState ( ) ;
if ( dayStyle ! = null )
( ( IStateManager ) dayStyle ) . TrackViewState ( ) ;
if ( dayHeaderStyle ! = null )
( ( IStateManager ) dayHeaderStyle ) . TrackViewState ( ) ;
if ( todayDayStyle ! = null )
( ( IStateManager ) todayDayStyle ) . TrackViewState ( ) ;
if ( weekendDayStyle ! = null )
( ( IStateManager ) weekendDayStyle ) . TrackViewState ( ) ;
if ( otherMonthDayStyle ! = null )
( ( IStateManager ) otherMonthDayStyle ) . TrackViewState ( ) ;
if ( selectedDayStyle ! = null )
( ( IStateManager ) selectedDayStyle ) . TrackViewState ( ) ;
if ( selectorStyle ! = null )
( ( IStateManager ) selectorStyle ) . TrackViewState ( ) ;
}
/// <devdoc>
/// </devdoc>
private int NumericFirstDayOfWeek ( ) {
// Used globalized value by default
return ( FirstDayOfWeek = = FirstDayOfWeek . Default )
? ( int ) DateTimeFormatInfo . CurrentInfo . FirstDayOfWeek
: ( int ) FirstDayOfWeek ;
}
/// <devdoc>
/// <para>Raises the <see langword='DayRender '/>event for a <see cref='System.Web.UI.WebControls.Calendar'/>.</para>
/// </devdoc>
protected virtual void OnDayRender ( TableCell cell , CalendarDay day ) {
DayRenderEventHandler handler = ( DayRenderEventHandler ) Events [ EventDayRender ] ;
if ( handler ! = null ) {
int absoluteDay = day . Date . Subtract ( baseDate ) . Days ;
// VSWhidbey 215383: We return null for selectUrl if a control is not in
// the page control tree.
string selectUrl = null ;
Page page = Page ;
if ( page ! = null ) {
string eventArgument = absoluteDay . ToString ( CultureInfo . InvariantCulture ) ;
selectUrl = Page . ClientScript . GetPostBackClientHyperlink ( this , eventArgument , true ) ;
}
handler ( this , new DayRenderEventArgs ( cell , day , selectUrl ) ) ;
}
}
/// <devdoc>
/// <para>Raises the <see langword='SelectionChanged '/>event for a <see cref='System.Web.UI.WebControls.Calendar'/>.</para>
/// </devdoc>
protected virtual void OnSelectionChanged ( ) {
EventHandler handler = ( EventHandler ) Events [ EventSelectionChanged ] ;
if ( handler ! = null ) {
handler ( this , EventArgs . Empty ) ;
}
}
/// <devdoc>
/// <para>Raises the <see langword='VisibleMonthChanged '/>event for a <see cref='System.Web.UI.WebControls.Calendar'/>.</para>
/// </devdoc>
protected virtual void OnVisibleMonthChanged ( DateTime newDate , DateTime previousDate ) {
MonthChangedEventHandler handler = ( MonthChangedEventHandler ) Events [ EventVisibleMonthChanged ] ;
if ( handler ! = null ) {
handler ( this , new MonthChangedEventArgs ( newDate , previousDate ) ) ;
}
}
/// <internalonly/>
/// <devdoc>
/// <para>Raises events on post back for the <see cref='System.Web.UI.WebControls.Calendar'/> control.</para>
/// </devdoc>
protected virtual void RaisePostBackEvent ( string eventArgument ) {
ValidateEvent ( UniqueID , eventArgument ) ;
if ( AdapterInternal ! = null ) {
IPostBackEventHandler pbeh = AdapterInternal as IPostBackEventHandler ;
if ( pbeh ! = null ) {
pbeh . RaisePostBackEvent ( eventArgument ) ;
}
} else {
if ( String . Compare ( eventArgument , 0 , NAVIGATE_MONTH_COMMAND , 0 , NAVIGATE_MONTH_COMMAND . Length , StringComparison . Ordinal ) = = 0 ) {
// Month navigation. The command starts with a "V" and the remainder is day difference from the
// base date.
DateTime oldDate = VisibleDate ;
if ( oldDate . Equals ( DateTime . MinValue ) ) {
oldDate = TodaysDate ;
}
int newDateDiff = Int32 . Parse ( eventArgument . Substring ( NAVIGATE_MONTH_COMMAND . Length ) , CultureInfo . InvariantCulture ) ;
VisibleDate = baseDate . AddDays ( newDateDiff ) ;
if ( VisibleDate = = DateTime . MinValue ) {
// MinValue would make the calendar shows today's month instead because it
// is the default value of VisibleDate property, so we add a day to keep
// showing the first supported month.
// We assume the first supported month has more than one day.
VisibleDate = DateTimeFormatInfo . CurrentInfo . Calendar . AddDays ( VisibleDate , 1 ) ;
}
OnVisibleMonthChanged ( VisibleDate , oldDate ) ;
}
else if ( String . Compare ( eventArgument , 0 , SELECT_RANGE_COMMAND , 0 , SELECT_RANGE_COMMAND . Length , StringComparison . Ordinal ) = = 0 ) {
// Range selection. The command starts with an "R". The remainder is an integer. When divided by 100
// the result is the day difference from the base date of the first day, and the remainder is the
// number of days to select.
int rangeValue = Int32 . Parse ( eventArgument . Substring ( SELECT_RANGE_COMMAND . Length ) , CultureInfo . InvariantCulture ) ;
int dayDiff = rangeValue / 100 ;
int dayRange = rangeValue % 100 ;
if ( dayRange < 1 ) {
dayRange = 100 + dayRange ;
dayDiff - = 1 ;
}
DateTime dt = baseDate . AddDays ( dayDiff ) ;
SelectRange ( dt , dt . AddDays ( dayRange - 1 ) ) ;
}
else {
// Single day selection. This is just a number which is the day difference from the base date.
int dayDiff = Int32 . Parse ( eventArgument , CultureInfo . InvariantCulture ) ;
DateTime dt = baseDate . AddDays ( dayDiff ) ;
SelectRange ( dt , dt ) ;
}
}
}
void IPostBackEventHandler . RaisePostBackEvent ( string eventArgument ) {
RaisePostBackEvent ( eventArgument ) ;
}
/// <internalonly/>
protected internal override void OnPreRender ( EventArgs e ) {
base . OnPreRender ( e ) ;
if ( Page ! = null ) {
Page . RegisterPostBackScript ( ) ;
}
}
/// <internalonly/>
/// <devdoc>
/// <para>Displays the <see cref='System.Web.UI.WebControls.Calendar'/> control on the client.</para>
/// </devdoc>
protected internal override void Render ( HtmlTextWriter writer ) {
threadCalendar = DateTimeFormatInfo . CurrentInfo . Calendar ;
minSupportedDate = threadCalendar . MinSupportedDateTime ;
maxSupportedDate = threadCalendar . MaxSupportedDateTime ;
#if DEBUG
threadCalendarInitialized = true ;
#endif
DateTime visibleDate = EffectiveVisibleDate ( ) ;
DateTime firstDay = FirstCalendarDay ( visibleDate ) ;
CalendarSelectionMode selectionMode = SelectionMode ;
// Make sure we are in a form tag with runat=server.
if ( Page ! = null ) {
Page . VerifyRenderingInServerForm ( this ) ;
}
// We only want to display the link if we have a page, or if we are on the design surface
// If we can stops links being active on the Autoformat dialog, then we can remove this these checks.
Page page = Page ;
bool buttonsActive ;
if ( page = = null | | DesignMode ) {
buttonsActive = false ;
}
else {
buttonsActive = IsEnabled ;
}
defaultForeColor = ForeColor ;
if ( defaultForeColor = = Color . Empty ) {
defaultForeColor = DefaultForeColor ;
}
defaultButtonColorText = ColorTranslator . ToHtml ( defaultForeColor ) ;
Table table = new Table ( ) ;
if ( ID ! = null ) {
table . ID = ClientID ;
}
table . CopyBaseAttributes ( this ) ;
if ( ControlStyleCreated ) {
table . ApplyStyle ( ControlStyle ) ;
}
table . Width = Width ;
table . Height = Height ;
table . CellPadding = CellPadding ;
table . CellSpacing = CellSpacing ;
// default look
if ( ( ControlStyleCreated = = false ) | |
( ControlStyle . IsSet ( System . Web . UI . WebControls . Style . PROP_BORDERWIDTH ) = = false ) | |
BorderWidth . Equals ( Unit . Empty ) ) {
table . BorderWidth = Unit . Pixel ( 1 ) ;
}
if ( ShowGridLines ) {
table . GridLines = GridLines . Both ;
}
else {
table . GridLines = GridLines . None ;
}
bool useAccessibleHeader = UseAccessibleHeader ;
if ( useAccessibleHeader ) {
if ( table . Attributes [ "title" ] = = null ) {
table . Attributes [ "title" ] = SR . GetString ( SR . Calendar_TitleText ) ;
}
}
string caption = Caption ;
if ( caption . Length > 0 ) {
table . Caption = caption ;
table . CaptionAlign = CaptionAlign ;
}
table . RenderBeginTag ( writer ) ;
if ( ShowTitle ) {
RenderTitle ( writer , visibleDate , selectionMode , buttonsActive , useAccessibleHeader ) ;
}
if ( ShowDayHeader ) {
RenderDayHeader ( writer , visibleDate , selectionMode , buttonsActive , useAccessibleHeader ) ;
}
RenderDays ( writer , firstDay , visibleDate , selectionMode , buttonsActive , useAccessibleHeader ) ;
table . RenderEndTag ( writer ) ;
}
private void RenderCalendarCell ( HtmlTextWriter writer , TableItemStyle style , string text , string title , bool hasButton , string eventArgument ) {
style . AddAttributesToRender ( writer , this ) ;
writer . RenderBeginTag ( HtmlTextWriterTag . Td ) ;
if ( hasButton ) {
// render the button
Color foreColor = style . ForeColor ;
writer . Write ( "<a href=\"" ) ;
writer . Write ( Page . ClientScript . GetPostBackClientHyperlink ( this , eventArgument , true ) ) ;
// ForeColor needs to go on the actual link. This breaks the uplevel/downlevel rules a little bit,
// but it is worth doing so the day links do not change color when they go in the history on
// downlevel browsers. Otherwise, people get it confused with the selection mechanism.
writer . Write ( "\" style=\"color:" ) ;
writer . Write ( foreColor . IsEmpty ? defaultButtonColorText : ColorTranslator . ToHtml ( foreColor ) ) ;
if ( ! String . IsNullOrEmpty ( title ) ) {
writer . Write ( "\" title=\"" ) ;
writer . Write ( title ) ;
}
writer . Write ( "\">" ) ;
writer . Write ( text ) ;
writer . Write ( "</a>" ) ;
}
else {
writer . Write ( text ) ;
}
writer . RenderEndTag ( ) ;
}
private void RenderCalendarHeaderCell ( HtmlTextWriter writer , TableItemStyle style , string text , string abbrText ) {
style . AddAttributesToRender ( writer , this ) ;
writer . AddAttribute ( "abbr" , abbrText ) ;
writer . AddAttribute ( "scope" , "col" ) ;
writer . RenderBeginTag ( HtmlTextWriterTag . Th ) ;
writer . Write ( text ) ;
writer . RenderEndTag ( ) ;
}
/// <devdoc>
/// </devdoc>
private void RenderDayHeader ( HtmlTextWriter writer , DateTime visibleDate , CalendarSelectionMode selectionMode , bool buttonsActive , bool useAccessibleHeader ) {
writer . Write ( ROWBEGINTAG ) ;
DateTimeFormatInfo dtf = DateTimeFormatInfo . CurrentInfo ;
if ( HasWeekSelectors ( selectionMode ) ) {
TableItemStyle monthSelectorStyle = new TableItemStyle ( ) ;
monthSelectorStyle . HorizontalAlign = HorizontalAlign . Center ;
// add the month selector button if required;
if ( selectionMode = = CalendarSelectionMode . DayWeekMonth ) {
// Range selection. The command starts with an "R". The remainder is an integer. When divided by 100
// the result is the day difference from the base date of the first day, and the remainder is the
// number of days to select.
int startOffset = visibleDate . Subtract ( baseDate ) . Days ;
int monthLength = threadCalendar . GetDaysInMonth ( threadCalendar . GetYear ( visibleDate ) , threadCalendar . GetMonth ( visibleDate ) , threadCalendar . GetEra ( visibleDate ) ) ;
if ( IsMinSupportedYearMonth ( visibleDate ) ) {
// The first supported month might not start with day 1
// (e.g. Sept 8 is the first supported date of JapaneseCalendar)
monthLength = monthLength - threadCalendar . GetDayOfMonth ( visibleDate ) + 1 ;
}
else if ( IsMaxSupportedYearMonth ( visibleDate ) ) {
// The last supported month might not have all days supported in that calendar month
// (e.g. April 3 is the last supported date of HijriCalendar)
monthLength = threadCalendar . GetDayOfMonth ( maxSupportedDate ) ;
}
string monthSelectKey = SELECT_RANGE_COMMAND + ( ( startOffset * 100 ) + monthLength ) . ToString ( CultureInfo . InvariantCulture ) ;
monthSelectorStyle . CopyFrom ( SelectorStyle ) ;
string selectMonthTitle = null ;
if ( useAccessibleHeader ) {
selectMonthTitle = SR . GetString ( SR . Calendar_SelectMonthTitle ) ;
}
RenderCalendarCell ( writer , monthSelectorStyle , SelectMonthText , selectMonthTitle , buttonsActive , monthSelectKey ) ;
}
else {
// otherwise make it look like the header row
monthSelectorStyle . CopyFrom ( DayHeaderStyle ) ;
RenderCalendarCell ( writer , monthSelectorStyle , string . Empty , null , false , null ) ;
}
}
TableItemStyle dayNameStyle = new TableItemStyle ( ) ;
dayNameStyle . HorizontalAlign = HorizontalAlign . Center ;
dayNameStyle . CopyFrom ( DayHeaderStyle ) ;
DayNameFormat dayNameFormat = DayNameFormat ;
int numericFirstDay = NumericFirstDayOfWeek ( ) ;
for ( int i = numericFirstDay ; i < numericFirstDay + 7 ; i + + ) {
string dayName ;
int dayOfWeek = i % 7 ;
switch ( dayNameFormat ) {
case DayNameFormat . FirstLetter :
dayName = dtf . GetDayName ( ( DayOfWeek ) dayOfWeek ) . Substring ( 0 , 1 ) ;
break ;
case DayNameFormat . FirstTwoLetters :
dayName = dtf . GetDayName ( ( DayOfWeek ) dayOfWeek ) . Substring ( 0 , 2 ) ;
break ;
case DayNameFormat . Full :
dayName = dtf . GetDayName ( ( DayOfWeek ) dayOfWeek ) ;
break ;
case DayNameFormat . Short :
dayName = dtf . GetAbbreviatedDayName ( ( DayOfWeek ) dayOfWeek ) ;
break ;
case DayNameFormat . Shortest :
dayName = dtf . GetShortestDayName ( ( DayOfWeek ) dayOfWeek ) ;
break ;
default :
Debug . Assert ( false , "Unknown DayNameFormat value!" ) ;
goto case DayNameFormat . Short ;
}
if ( useAccessibleHeader ) {
string fullDayName = dtf . GetDayName ( ( DayOfWeek ) dayOfWeek ) ;
RenderCalendarHeaderCell ( writer , dayNameStyle , dayName , fullDayName ) ;
}
else {
RenderCalendarCell ( writer , dayNameStyle , dayName , null , false , null ) ;
}
}
writer . Write ( ROWENDTAG ) ;
}
/// <devdoc>
/// </devdoc>
private void RenderDays ( HtmlTextWriter writer , DateTime firstDay , DateTime visibleDate , CalendarSelectionMode selectionMode , bool buttonsActive , bool useAccessibleHeader ) {
// Now add the rows for the actual days
DateTime d = firstDay ;
TableItemStyle weekSelectorStyle = null ;
Unit defaultWidth ;
bool hasWeekSelectors = HasWeekSelectors ( selectionMode ) ;
if ( hasWeekSelectors ) {
weekSelectorStyle = new TableItemStyle ( ) ;
weekSelectorStyle . Width = Unit . Percentage ( 12 ) ;
weekSelectorStyle . HorizontalAlign = HorizontalAlign . Center ;
weekSelectorStyle . CopyFrom ( SelectorStyle ) ;
defaultWidth = Unit . Percentage ( 12 ) ;
}
else {
defaultWidth = Unit . Percentage ( 14 ) ;
}
// This determines whether we need to call DateTime.ToString for each day. The only culture/calendar
// that requires this for now is the HebrewCalendar.
bool usesStandardDayDigits = ! ( threadCalendar is HebrewCalendar ) ;
// This determines whether we can write out cells directly, or whether we have to create whole
// TableCell objects for each day.
bool hasRenderEvent = ( this . GetType ( ) ! = typeof ( Calendar )
| | Events [ EventDayRender ] ! = null ) ;
TableItemStyle [ ] cellStyles = new TableItemStyle [ 16 ] ;
int definedStyleMask = GetDefinedStyleMask ( ) ;
DateTime todaysDate = TodaysDate ;
string selectWeekText = SelectWeekText ;
bool daysSelectable = buttonsActive & & ( selectionMode ! = CalendarSelectionMode . None ) ;
int visibleDateMonth = threadCalendar . GetMonth ( visibleDate ) ;
int absoluteDay = firstDay . Subtract ( baseDate ) . Days ;
// VSWhidbey 480155: flag to indicate if forecolor needs to be set
// explicitly in design mode to mimic runtime rendering with the
// limitation of not supporting CSS class color setting.
bool inDesignSelectionMode = ( DesignMode & & SelectionMode ! = CalendarSelectionMode . None ) ;
//------------------------------------------------------------------
// VSWhidbey 366243: The following variables are for boundary cases
// such as the current visible month is the first or the last
// supported month. They are used in the 'for' loops below.
// For the first supported month, calculate how many days to
// skip at the beginning of the first month. E.g. JapaneseCalendar
// starts at Sept 8.
int numOfFirstDaysToSkip = 0 ;
if ( IsMinSupportedYearMonth ( visibleDate ) ) {
numOfFirstDaysToSkip = ( int ) threadCalendar . GetDayOfWeek ( firstDay ) - NumericFirstDayOfWeek ( ) ;
// If negative, it simply means the the index of the starting
// day name is greater than the day name of the first supported
// date. We add back 7 to get the number of days to skip.
if ( numOfFirstDaysToSkip < 0 ) {
numOfFirstDaysToSkip + = 7 ;
}
}
Debug . Assert ( numOfFirstDaysToSkip < 7 ) ;
// For the last or second last supported month, initialize variables
// to identify the last supported date of the current calendar.
// e.g. The last supported date of HijriCalendar is April 3. When
// the second last monthh is shown, it can be the case that not all
// cells will be filled up.
bool passedLastSupportedDate = false ;
DateTime secondLastMonth = threadCalendar . AddMonths ( maxSupportedDate , - 1 ) ;
bool lastOrSecondLastMonth = ( IsMaxSupportedYearMonth ( visibleDate ) | |
IsTheSameYearMonth ( secondLastMonth , visibleDate ) ) ;
//------------------------------------------------------------------
for ( int iRow = 0 ; iRow < 6 ; iRow + + ) {
if ( passedLastSupportedDate ) {
break ;
}
writer . Write ( ROWBEGINTAG ) ;
// add week selector column and button if required
if ( hasWeekSelectors ) {
// Range selection. The command starts with an "R". The remainder is an integer. When divided by 100
// the result is the day difference from the base date of the first day, and the remainder is the
// number of days to select.
int dayDiffParameter = ( absoluteDay * 100 ) + 7 ;
// Adjust the dayDiff for the first or the last supported month
if ( numOfFirstDaysToSkip > 0 ) {
dayDiffParameter - = numOfFirstDaysToSkip ;
}
else if ( lastOrSecondLastMonth ) {
int daysFromLastDate = maxSupportedDate . Subtract ( d ) . Days ;
if ( daysFromLastDate < 6 ) {
dayDiffParameter - = ( 6 - daysFromLastDate ) ;
}
}
string weekSelectKey = SELECT_RANGE_COMMAND + dayDiffParameter . ToString ( CultureInfo . InvariantCulture ) ;
string selectWeekTitle = null ;
if ( useAccessibleHeader ) {
int weekOfMonth = iRow + 1 ;
selectWeekTitle = SR . GetString ( SR . Calendar_SelectWeekTitle , weekOfMonth . ToString ( CultureInfo . InvariantCulture ) ) ;
}
RenderCalendarCell ( writer , weekSelectorStyle , selectWeekText , selectWeekTitle , buttonsActive , weekSelectKey ) ;
}
for ( int iDay = 0 ; iDay < 7 ; iDay + + ) {
// Render empty cells for special cases to handle the first
// or last supported month.
if ( numOfFirstDaysToSkip > 0 ) {
iDay + = numOfFirstDaysToSkip ;
for ( ; numOfFirstDaysToSkip > 0 ; numOfFirstDaysToSkip - - ) {
writer . RenderBeginTag ( HtmlTextWriterTag . Td ) ;
writer . RenderEndTag ( ) ;
}
}
else if ( passedLastSupportedDate ) {
for ( ; iDay < 7 ; iDay + + ) {
writer . RenderBeginTag ( HtmlTextWriterTag . Td ) ;
writer . RenderEndTag ( ) ;
}
break ;
}
int dayOfWeek = ( int ) threadCalendar . GetDayOfWeek ( d ) ;
int dayOfMonth = threadCalendar . GetDayOfMonth ( d ) ;
string dayNumberText ;
if ( ( dayOfMonth < = cachedNumberMax ) & & usesStandardDayDigits ) {
dayNumberText = cachedNumbers [ dayOfMonth ] ;
}
else {
dayNumberText = d . ToString ( "dd" , CultureInfo . CurrentCulture ) ;
}
CalendarDay day = new CalendarDay ( d ,
( dayOfWeek = = 0 | | dayOfWeek = = 6 ) , // IsWeekend
d . Equals ( todaysDate ) , // IsToday
( selectedDates ! = null ) & & selectedDates . Contains ( d ) , // IsSelected
threadCalendar . GetMonth ( d ) ! = visibleDateMonth , // IsOtherMonth
dayNumberText // Number Text
) ;
int styleMask = STYLEMASK_DAY ;
if ( day . IsSelected )
styleMask | = STYLEMASK_SELECTED ;
if ( day . IsOtherMonth )
styleMask | = STYLEMASK_OTHERMONTH ;
if ( day . IsToday )
styleMask | = STYLEMASK_TODAY ;
if ( day . IsWeekend )
styleMask | = STYLEMASK_WEEKEND ;
int dayStyleMask = definedStyleMask & styleMask ;
// determine the unique portion of the mask for the current calendar,
// which will strip out the day style bit
int dayStyleID = dayStyleMask & STYLEMASK_UNIQUE ;
TableItemStyle cellStyle = cellStyles [ dayStyleID ] ;
if ( cellStyle = = null ) {
cellStyle = new TableItemStyle ( ) ;
SetDayStyles ( cellStyle , dayStyleMask , defaultWidth ) ;
cellStyles [ dayStyleID ] = cellStyle ;
}
string dayTitle = null ;
if ( useAccessibleHeader ) {
dayTitle = d . ToString ( "m" , CultureInfo . CurrentCulture ) ;
}
if ( hasRenderEvent ) {
TableCell cdc = new TableCell ( ) ;
cdc . ApplyStyle ( cellStyle ) ;
LiteralControl dayContent = new LiteralControl ( dayNumberText ) ;
cdc . Controls . Add ( dayContent ) ;
day . IsSelectable = daysSelectable ;
OnDayRender ( cdc , day ) ;
// refresh the day content
dayContent . Text = GetCalendarButtonText ( absoluteDay . ToString ( CultureInfo . InvariantCulture ) ,
dayNumberText ,
dayTitle ,
buttonsActive & & day . IsSelectable ,
cdc . ForeColor ) ;
cdc . RenderControl ( writer ) ;
}
else {
// VSWhidbey 480155: In design mode we render days as
// texts instead of links so CSS class color setting is
// supported. But this differs in runtime rendering
// where CSS class color setting is not supported. To
// correctly mimic the forecolor of runtime rendering in
// design time, the default color, which is used in
// runtime rendering, is explicitly set in this case.
if ( inDesignSelectionMode & & cellStyle . ForeColor . IsEmpty ) {
cellStyle . ForeColor = defaultForeColor ;
}
RenderCalendarCell ( writer , cellStyle , dayNumberText , dayTitle , daysSelectable , absoluteDay . ToString ( CultureInfo . InvariantCulture ) ) ;
}
Debug . Assert ( ! passedLastSupportedDate ) ;
if ( lastOrSecondLastMonth & & d . Month = = maxSupportedDate . Month & & d . Day = = maxSupportedDate . Day ) {
passedLastSupportedDate = true ;
}
else {
d = threadCalendar . AddDays ( d , 1 ) ;
absoluteDay + + ;
}
}
writer . Write ( ROWENDTAG ) ;
}
}
/// <devdoc>
/// </devdoc>
private void RenderTitle ( HtmlTextWriter writer , DateTime visibleDate , CalendarSelectionMode selectionMode , bool buttonsActive , bool useAccessibleHeader ) {
writer . Write ( ROWBEGINTAG ) ;
TableCell titleCell = new TableCell ( ) ;
Table titleTable = new Table ( ) ;
// default title table/cell styles
titleCell . ColumnSpan = HasWeekSelectors ( selectionMode ) ? 8 : 7 ;
titleCell . BackColor = Color . Silver ;
titleTable . GridLines = GridLines . None ;
titleTable . Width = Unit . Percentage ( 100 ) ;
titleTable . CellSpacing = 0 ;
TableItemStyle titleStyle = TitleStyle ;
ApplyTitleStyle ( titleCell , titleTable , titleStyle ) ;
titleCell . RenderBeginTag ( writer ) ;
titleTable . RenderBeginTag ( writer ) ;
writer . Write ( ROWBEGINTAG ) ;
NextPrevFormat nextPrevFormat = NextPrevFormat ;
TableItemStyle nextPrevStyle = new TableItemStyle ( ) ;
nextPrevStyle . Width = Unit . Percentage ( 15 ) ;
nextPrevStyle . CopyFrom ( NextPrevStyle ) ;
if ( ShowNextPrevMonth ) {
if ( IsMinSupportedYearMonth ( visibleDate ) ) {
writer . RenderBeginTag ( HtmlTextWriterTag . Td ) ;
writer . RenderEndTag ( ) ;
}
else {
string prevMonthText ;
if ( nextPrevFormat = = NextPrevFormat . ShortMonth | | nextPrevFormat = = NextPrevFormat . FullMonth ) {
int monthNo = threadCalendar . GetMonth ( threadCalendar . AddMonths ( visibleDate , - 1 ) ) ;
prevMonthText = GetMonthName ( monthNo , ( nextPrevFormat = = NextPrevFormat . FullMonth ) ) ;
}
else {
prevMonthText = PrevMonthText ;
}
// Month navigation. The command starts with a "V" and the remainder is day difference from the
// base date.
DateTime prevMonthDate ;
// VSWhidbey 366243: Some calendar's min supported date is
// not the first day of the month (e.g. JapaneseCalendar.
// So if we are setting the second supported month, the prev
// month link should always point to the first supported
// date instead of the first day of the previous month.
DateTime secondSupportedMonth = threadCalendar . AddMonths ( minSupportedDate , 1 ) ;
if ( IsTheSameYearMonth ( secondSupportedMonth , visibleDate ) ) {
prevMonthDate = minSupportedDate ;
}
else {
prevMonthDate = threadCalendar . AddMonths ( visibleDate , - 1 ) ;
}
string prevMonthKey = NAVIGATE_MONTH_COMMAND + ( prevMonthDate . Subtract ( baseDate ) ) . Days . ToString ( CultureInfo . InvariantCulture ) ;
string previousMonthTitle = null ;
if ( useAccessibleHeader ) {
previousMonthTitle = SR . GetString ( SR . Calendar_PreviousMonthTitle ) ;
}
RenderCalendarCell ( writer , nextPrevStyle , prevMonthText , previousMonthTitle , buttonsActive , prevMonthKey ) ;
}
}
TableItemStyle cellMainStyle = new TableItemStyle ( ) ;
if ( titleStyle . HorizontalAlign ! = HorizontalAlign . NotSet ) {
cellMainStyle . HorizontalAlign = titleStyle . HorizontalAlign ;
}
else {
cellMainStyle . HorizontalAlign = HorizontalAlign . Center ;
}
cellMainStyle . Wrap = titleStyle . Wrap ;
cellMainStyle . Width = Unit . Percentage ( 70 ) ;
string titleText ;
switch ( TitleFormat ) {
case TitleFormat . Month :
titleText = visibleDate . ToString ( "MMMM" , CultureInfo . CurrentCulture ) ;
break ;
case TitleFormat . MonthYear :
string titlePattern = DateTimeFormatInfo . CurrentInfo . YearMonthPattern ;
// Some cultures have a comma in their YearMonthPattern, which does not look
// right in a calendar. Use a fixed pattern for those.
if ( titlePattern . IndexOf ( ',' ) > = 0 ) {
titlePattern = "MMMM yyyy" ;
}
titleText = visibleDate . ToString ( titlePattern , CultureInfo . CurrentCulture ) ;
break ;
default :
Debug . Assert ( false , "Unknown TitleFormat value!" ) ;
goto case TitleFormat . MonthYear ;
}
RenderCalendarCell ( writer , cellMainStyle , titleText , null , false , null ) ;
if ( ShowNextPrevMonth ) {
if ( IsMaxSupportedYearMonth ( visibleDate ) ) {
writer . RenderBeginTag ( HtmlTextWriterTag . Td ) ;
writer . RenderEndTag ( ) ;
}
else {
// Style for this one is identical bar
nextPrevStyle . HorizontalAlign = HorizontalAlign . Right ;
string nextMonthText ;
if ( nextPrevFormat = = NextPrevFormat . ShortMonth | | nextPrevFormat = = NextPrevFormat . FullMonth ) {
int monthNo = threadCalendar . GetMonth ( threadCalendar . AddMonths ( visibleDate , 1 ) ) ;
nextMonthText = GetMonthName ( monthNo , ( nextPrevFormat = = NextPrevFormat . FullMonth ) ) ;
}
else {
nextMonthText = NextMonthText ;
}
// Month navigation. The command starts with a "V" and the remainder is day difference from the
// base date.
DateTime nextMonthDate = threadCalendar . AddMonths ( visibleDate , 1 ) ;
string nextMonthKey = NAVIGATE_MONTH_COMMAND + ( nextMonthDate . Subtract ( baseDate ) ) . Days . ToString ( CultureInfo . InvariantCulture ) ;
string nextMonthTitle = null ;
if ( useAccessibleHeader ) {
nextMonthTitle = SR . GetString ( SR . Calendar_NextMonthTitle ) ;
}
RenderCalendarCell ( writer , nextPrevStyle , nextMonthText , nextMonthTitle , buttonsActive , nextMonthKey ) ;
}
}
writer . Write ( ROWENDTAG ) ;
titleTable . RenderEndTag ( writer ) ;
titleCell . RenderEndTag ( writer ) ;
writer . Write ( ROWENDTAG ) ;
}
/// <internalonly/>
/// <devdoc>
/// <para>Stores the state of the System.Web.UI.WebControls.Calender.</para>
/// </devdoc>
protected override object SaveViewState ( ) {
if ( SelectedDates . Count > 0 )
ViewState [ "SD" ] = dateList ;
object [ ] myState = new object [ 10 ] ;
myState [ 0 ] = base . SaveViewState ( ) ;
myState [ 1 ] = ( titleStyle ! = null ) ? ( ( IStateManager ) titleStyle ) . SaveViewState ( ) : null ;
myState [ 2 ] = ( nextPrevStyle ! = null ) ? ( ( IStateManager ) nextPrevStyle ) . SaveViewState ( ) : null ;
myState [ 3 ] = ( dayStyle ! = null ) ? ( ( IStateManager ) dayStyle ) . SaveViewState ( ) : null ;
myState [ 4 ] = ( dayHeaderStyle ! = null ) ? ( ( IStateManager ) dayHeaderStyle ) . SaveViewState ( ) : null ;
myState [ 5 ] = ( todayDayStyle ! = null ) ? ( ( IStateManager ) todayDayStyle ) . SaveViewState ( ) : null ;
myState [ 6 ] = ( weekendDayStyle ! = null ) ? ( ( IStateManager ) weekendDayStyle ) . SaveViewState ( ) : null ;
myState [ 7 ] = ( otherMonthDayStyle ! = null ) ? ( ( IStateManager ) otherMonthDayStyle ) . SaveViewState ( ) : null ;
myState [ 8 ] = ( selectedDayStyle ! = null ) ? ( ( IStateManager ) selectedDayStyle ) . SaveViewState ( ) : null ;
myState [ 9 ] = ( selectorStyle ! = null ) ? ( ( IStateManager ) selectorStyle ) . SaveViewState ( ) : null ;
for ( int i = 0 ; i < myState . Length ; i + + ) {
if ( myState [ i ] ! = null )
return myState ;
}
return null ;
}
private void SelectRange ( DateTime dateFrom , DateTime dateTo ) {
Debug . Assert ( dateFrom < = dateTo , "Bad Date Range" ) ;
// see if this range differs in any way from the current range
// these checks will determine this because the colleciton is sorted
TimeSpan ts = dateTo - dateFrom ;
if ( SelectedDates . Count ! = ts . Days + 1
| | SelectedDates [ 0 ] ! = dateFrom
| | SelectedDates [ SelectedDates . Count - 1 ] ! = dateTo ) {
SelectedDates . SelectRange ( dateFrom , dateTo ) ;
OnSelectionChanged ( ) ;
}
}
/// <devdoc>
/// </devdoc>
private void SetDayStyles ( TableItemStyle style , int styleMask , Unit defaultWidth ) {
// default day styles
style . Width = defaultWidth ;
style . HorizontalAlign = HorizontalAlign . Center ;
if ( ( styleMask & STYLEMASK_DAY ) ! = 0 ) {
style . CopyFrom ( DayStyle ) ;
}
if ( ( styleMask & STYLEMASK_WEEKEND ) ! = 0 ) {
style . CopyFrom ( WeekendDayStyle ) ;
}
if ( ( styleMask & STYLEMASK_OTHERMONTH ) ! = 0 ) {
style . CopyFrom ( OtherMonthDayStyle ) ;
}
if ( ( styleMask & STYLEMASK_TODAY ) ! = 0 ) {
style . CopyFrom ( TodayDayStyle ) ;
}
if ( ( styleMask & STYLEMASK_SELECTED ) ! = 0 ) {
// default selected day style
style . ForeColor = Color . White ;
style . BackColor = Color . Silver ;
style . CopyFrom ( SelectedDayStyle ) ;
}
}
}
}