#if FRAMEWORK20 using System; using System.Collections.Generic; using System.Text; using System.ComponentModel; using System.Globalization; namespace DevComponents.Editors.DateTimeAdv { public class DateTimeGroup : VisualInputGroup { #region Private Variables private IDateTimePartInput _DayInput = null; private IDateTimePartInput _MonthInput = null; private IDateTimePartInput _YearInput = null; private IDateTimePartInput _HourInput = null; private IDateTimePartInput _MinuteInput = null; private IDateTimePartInput _SecondInput = null; private IDateTimePartInput _DayOfYearInput = null; /// /// Gets the minimum date value of the DateTimePicker control. /// public static readonly System.DateTime MinDateTime = new System.DateTime(1753, 1, 1); /// /// Specifies the maximum date value of the DateTimePicker control. This field is read-only. /// public static readonly System.DateTime MaxDateTime = new System.DateTime(9998, 12, 31); #endregion #region Events /// /// Occurs when Value or IsEmpty property has changed. /// public event EventHandler ValueChanged; #endregion #region Constructor #endregion #region Internal Implementation protected override void OnItemsCollectionChanged(CollectionChangedInfo collectionChangedInfo) { if (collectionChangedInfo.ChangeType == eCollectionChangeType.Cleared) { _DayInput = null; _MonthInput = null; _YearInput = null; _HourInput = null; _MinuteInput = null; _SecondInput = null; _DayOfYearInput = null; } if (collectionChangedInfo.Removed != null) { foreach (VisualItem item in collectionChangedInfo.Removed) { if (item == _DayInput) _DayInput = null; else if (item == _MonthInput) _MonthInput = null; else if (item == _YearInput) _YearInput = null; else if (item == _HourInput) _HourInput = null; else if (item == _MinuteInput) _MinuteInput = null; else if (item == _SecondInput) _SecondInput = null; else if (item == _DayOfYearInput) _DayOfYearInput = null; } } if (collectionChangedInfo.Added != null) { List hourLabels = new List(); foreach (VisualItem item in collectionChangedInfo.Added) { if (item is HourPeriodLabel) { if (_HourInput != null && _HourInput is NumericHourInput) ((HourPeriodLabel)item).HourInput = (NumericHourInput)_HourInput; } else if (item is HourPeriodInput) { if (_HourInput != null && _HourInput is NumericHourInput) ((HourPeriodInput)item).HourInput = (NumericHourInput)_HourInput; } IDateTimePartInput idp = item as IDateTimePartInput; if (idp == null) continue; if (idp.Part == eDateTimePart.Day) _DayInput = idp; else if (idp.Part == eDateTimePart.Hour) { _HourInput = idp; if (_HourInput is NumericHourInput) { foreach (VisualItem vi in this.Items) { if (vi is HourPeriodLabel) ((HourPeriodLabel)vi).HourInput = (NumericHourInput)_HourInput; else if (vi is HourPeriodInput) ((HourPeriodInput)vi).HourInput = (NumericHourInput)_HourInput; } } } else if (idp.Part == eDateTimePart.Minute) _MinuteInput = idp; else if (idp.Part == eDateTimePart.Month) _MonthInput = idp; else if (idp.Part == eDateTimePart.Second) _SecondInput = idp; else if (idp.Part == eDateTimePart.Year) _YearInput = idp; else if (idp.Part == eDateTimePart.DayOfYear) _DayOfYearInput = idp; } } UpdateInnerDateTimeGroupMinMax(); UpdateInputItems(); base.OnItemsCollectionChanged(collectionChangedInfo); } private bool _ProcessingInputChanged = false; protected override void OnInputChanged(VisualInputBase input) { if (!_ProcessingInputChanged && !_ResettingDateValue) { try { _ProcessingInputChanged = true; if (input == _MonthInput || input == _YearInput) { if (_DayInput != null) { // Assign day min max values UpdateDayMaxValue(); } } if (input == _YearInput && _DayOfYearInput != null) UpdateDayOfYearMaxValue(); if (input != _YearInput && _YearInput != null && _YearInput.IsEmpty && _DefaultInputValues) _YearInput.Value = Math.Min(System.DateTime.Now.Year, _MaxDate.Year); if (input != _MonthInput && _MonthInput != null && _MonthInput.IsEmpty) { if (_DefaultInputValues) { if (_YearInput != null && _YearInput.Value == _MaxDate.Year) _MonthInput.Value = _MaxDate.Month; else _MonthInput.Value = System.DateTime.Now.Month; } // Assign day min max values UpdateDayMaxValue(); } if (input != _DayInput && _DayInput != null && _DayInput.IsEmpty && _DefaultInputValues) { if (_YearInput != null && _YearInput.Value == _MaxDate.Year && _MonthInput != null && _MonthInput.Value == _MaxDate.Month) _DayInput.Value = _MaxDate.Day; else _DayInput.Value = System.DateTime.Now.Day; } if (input != _HourInput && _HourInput != null && _HourInput.IsEmpty && _DefaultInputValues) { _HourInput.Value = 0; // System.DateTime.Now.Hour; } if (input != _MinuteInput && _MinuteInput != null && _MinuteInput.IsEmpty && _DefaultInputValues) { _MinuteInput.Value = 0; // System.DateTime.Now.Minute; } if (input != _SecondInput && _SecondInput != null && _SecondInput.IsEmpty && _DefaultInputValues) { _SecondInput.Value = 0; } // Reset empty flag if (_YearInput != null && !_YearInput.IsEmpty || _MonthInput != null && !_MonthInput.IsEmpty || _DayInput != null && !_DayInput.IsEmpty || _HourInput != null && !_HourInput.IsEmpty || _MinuteInput != null && !_MinuteInput.IsEmpty || _SecondInput != null && !_SecondInput.IsEmpty) this.IsEmpty = false; SyncValues(input); } finally { _ProcessingInputChanged = false; } if (IsUserInput && IsCurrentInputValid()) OnValueChanged(); } base.OnInputChanged(input); } private void UpdateDayOfYearMaxValue() { if (_YearInput != null && !_YearInput.IsEmpty && _DayOfYearInput != null) { _DayOfYearInput.MaxValue = DateTimeInput.GetActiveCulture().Calendar.GetDaysInYear(_YearInput.Value); } } protected override void OnFocusedItemChanged(VisualItem previousFocus) { if (this.FocusedItem == _DayInput && _DayInput is NumericDayInput) { UpdateDayMaxValue(); } else if (previousFocus == _YearInput || previousFocus == _DayInput) { UpdateDayMaxValue(); } else { SyncValues(previousFocus); } base.OnFocusedItemChanged(previousFocus); } private void UpdateDayMaxValue() { if (_DayInput != null && (this.FocusedItem == _DayInput || this.FocusedItem == _MonthInput) && _DayInput is NumericDayInput) _DayInput.MaxValue = 31; else if (_YearInput != null && _MonthInput != null && !_MonthInput.IsEmpty && _DayInput != null) { // Assign day min max values _DayInput.MaxValue = System.DateTime.DaysInMonth(_YearInput.IsEmpty ? System.DateTime.Now.Year : _YearInput.Value, _MonthInput.Value); } } protected override void OnInputComplete() { SyncValues(this.FocusedItem); base.OnInputComplete(); } //private bool _Validating = false; //protected override bool ValidateInput(VisualItem inputItem) //{ // if (!_Validating && inputItem is IDateTimePartInput && !this.IsEmpty) // { // IDateTimePartInput input = (IDateTimePartInput)inputItem; // System.DateTime v = GetCurrentInputValue(); // if (v < _MinDate || v > _MaxDate) // { // try // { // _Validating = true; // input.UndoInput(); // } // finally // { // _Validating = false; // } // return false; // } // } // return base.ValidateInput(inputItem); //} private void SyncValues(VisualItem visualItem) { IDateTimePartInput inputPart = visualItem as IDateTimePartInput; if (inputPart == null) return; for (int i = 0; i < this.Items.Count; i++) { IDateTimePartInput part = this.Items[i] as IDateTimePartInput; if (part == null) continue; if (part.Part == inputPart.Part && part != inputPart) part.Value = inputPart.Value; else if (part != inputPart && inputPart.Part == eDateTimePart.DayOfYear && (part.Part == eDateTimePart.Day || part.Part == eDateTimePart.Month)) { if (_YearInput != null && !_YearInput.IsEmpty) { System.DateTime d = CreateDateTime(_YearInput.Value, inputPart.Value); if (part.Part == eDateTimePart.Day) part.Value = d.Day; else if (part.Part == eDateTimePart.Month) part.Value = d.Month; } } else if (part.Part == eDateTimePart.DayName) { if (_YearInput != null && !_YearInput.IsEmpty && (_MonthInput != null && !_MonthInput.IsEmpty && _DayInput != null && !_DayInput.IsEmpty || _DayOfYearInput != null && !_DayOfYearInput.IsEmpty)) { try { System.DateTime date; if (_DayOfYearInput != null) date = CreateDateTime(_YearInput.Value, _DayOfYearInput.Value); else date = new System.DateTime(_YearInput.Value, _MonthInput.Value, _DayInput.Value); part.Value = (int)date.DayOfWeek; } catch { part.IsEmpty = true; } } else part.IsEmpty = true; } } } internal static System.DateTime CreateDateTime(int year, int dayOfYear) { System.DateTime d = new System.DateTime(year, 1, 1); if (dayOfYear > 0) { d.AddDays(dayOfYear - 1); } return d; } protected override void OnLostFocus() { UpdateValue(false); base.OnLostFocus(); } protected override void OnGroupInputComplete() { UpdateValue(false); base.OnGroupInputComplete(); } protected internal void UpdateValue(bool updateDirect) { // Validate Complete Input System.DateTime v = System.DateTime.Now; if (_YearInput != null && _YearInput.IsEmpty || _MonthInput != null && _MonthInput.IsEmpty || _DayInput != null && _DayInput.IsEmpty || _HourInput != null && _HourInput.IsEmpty || _MinuteInput != null && _MinuteInput.IsEmpty || _SecondInput != null && _SecondInput.IsEmpty) { if (HasNestedGroups) UpdateIsEmpty(); else { if (!this.IsFocused || _DefaultInputValues) this.IsEmpty = true; } } else { v = GetCurrentInputValue(); if (v > _MaxDate) v = _MaxDate; else if (v < _MinDate) v = _MinDate; if (updateDirect) _Value = v; else Value = v; } } private bool IsCurrentInputValid() { DateTime d = GetCurrentInputValue(); if (d < _MinDate || d > _MaxDate) return false; return true; } private bool HasNestedGroups { get { foreach (VisualItem item in this.Items) { if (item is VisualGroup) return true; } return false; } } private System.DateTime GetCurrentInputValue() { System.DateTime v = System.DateTime.Now; if (_Value != DateTime.MinValue) v = _Value; if (v < _MinDate) v = _MinDate; else if (v > _MaxDate) v = _MaxDate; int year = v.Year, month = v.Month, day = v.Day, hour = v.Hour, minute = v.Minute, second = v.Second, dayOfYear = v.DayOfYear; if (_YearInput != null) { year = _YearInput.Value; if (year < 30) year += 2000; else if (year < 100) year += 1900; } else if (_Value != DateTime.MinValue) year = _Value.Year; if (_MonthInput != null) month = _MonthInput.Value; else if (_Value != DateTime.MinValue) month = _Value.Month; if (_DayInput != null) { day = _DayInput.Value; if (_YearInput != null && _MonthInput != null) day = Math.Min(day, System.DateTime.DaysInMonth(_YearInput.IsEmpty ? System.DateTime.Now.Year : _YearInput.Value, _MonthInput.Value)); } else if (_Value != DateTime.MinValue) day = _Value.Day; if (_HourInput != null) { hour = _HourInput.Value; if (hour == 12 && _HourInput is NumericHourInput && ((NumericHourInput)_HourInput).Period == eHourPeriod.AM && !((NumericHourInput)_HourInput).Is24HourFormat) hour = 0; else if (hour < 12 && _HourInput is NumericHourInput && ((NumericHourInput)_HourInput).Period == eHourPeriod.PM && !((NumericHourInput)_HourInput).Is24HourFormat) { hour += 12; } } else if (_Value != DateTime.MinValue) hour = _Value.Hour; if (_MinuteInput != null) minute = _MinuteInput.Value; else if (_Value != DateTime.MinValue) minute = _Value.Minute; if (_SecondInput != null) second = _SecondInput.Value; else if (_Value != DateTime.MinValue) second = _Value.Second; else second = 0; if (_DayOfYearInput != null) { dayOfYear = _DayOfYearInput.Value; if (dayOfYear > 0) { System.DateTime d = CreateDateTime(year, dayOfYear); month = d.Month; day = d.Day; } } // Correct day for leap year etc. case if (System.DateTime.DaysInMonth(year, month) < day) day = System.DateTime.DaysInMonth(year, month); if (_HourInput != null || _MinuteInput != null || _SecondInput != null || _Value != DateTime.MinValue) v = new System.DateTime(year, month, day, hour, minute, second); else v = new System.DateTime(year, month, day); return v; } private System.DateTime _Value; /// /// Gets or sets the date time. /// public System.DateTime Value { get { if (this.IsFocused) this.UpdateValue(true); return _Value; } set { bool changed = _Value != value; _Value = value; this.IsEmpty = false; UpdateInputItems(); if(changed) OnValueChanged(); } } private bool _InValueChanged = false; /// /// Raises the ValueChanged event. /// protected virtual void OnValueChanged() { if (_InValueChanged) return; try { _InValueChanged = true; if (ValueChanged != null) ValueChanged(this, new EventArgs()); if (this.Parent is DateTimeGroup) ((DateTimeGroup)this.Parent).OnValueChanged(); this.InvalidateArrange(); } finally { _InValueChanged = false; } } /// /// Gets or sets the values of the nested DateTimeGroup items. /// [Browsable(false), DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden)] public System.DateTime[] Values { get { if (HasNestedGroups) { List dates = new List(); foreach (VisualItem item in this.Items) { DateTimeGroup group = item as DateTimeGroup; if (group != null) { dates.Add(group.Value); } } return dates.ToArray(); } return new System.DateTime[] { this.Value }; } set { if (value == null || value.Length == 0) return; if (HasNestedGroups) { int i = 0; foreach (VisualItem item in this.Items) { DateTimeGroup group = item as DateTimeGroup; if (group != null) { group.Value = value[i]; i++; if (i >= value.Length) break; } } } else this.Value = value[0]; } } private void UpdateInputItems() { System.DateTime d = _Value; if (_YearInput != null) { if (this.IsEmpty) _YearInput.IsEmpty = true; else _YearInput.Value = d.Year; } if (_MonthInput != null) { if (this.IsEmpty) _MonthInput.IsEmpty = true; else _MonthInput.Value = d.Month; } if (_DayInput != null) { if (this.IsEmpty) _DayInput.IsEmpty = true; else if (!(this.FocusedItem == _DayInput && _DayInput is NumericDayInput && _ProcessingInputChanged)) _DayInput.Value = d.Day; } if (_HourInput != null) { if (this.IsEmpty) _HourInput.IsEmpty = true; else { if (_HourInput is NumericHourInput) ((NumericHourInput)_HourInput).Period = eHourPeriod.AM; _HourInput.Value = d.Hour; if (_HourInput is NumericHourInput && !((NumericHourInput)_HourInput).Is24HourFormat && d.Hour >= 12) ((NumericHourInput)_HourInput).Period = eHourPeriod.PM; } } if (_MinuteInput != null) { if (this.IsEmpty) _MinuteInput.IsEmpty = true; else _MinuteInput.Value = d.Minute; } if (_SecondInput != null) { if (this.IsEmpty) _SecondInput.IsEmpty = true; else _SecondInput.Value = d.Second; } for (int i = 0; i < this.Items.Count; i++) { IDateTimePartInput part = this.Items[i] as IDateTimePartInput; if (part == null) continue; if (part.Part == eDateTimePart.DayName) part.Value = this.IsEmpty ? -1 : (int)_Value.DayOfWeek; else if (part.Part == eDateTimePart.DayOfYear) { if (this.IsEmpty) part.IsEmpty = true; else part.Value = _Value.DayOfYear; } } InvalidateArrange(); } private bool _ResettingDateValue = false; protected override void ResetValue() { _ResettingDateValue = true; try { if (this.AllowEmptyState) { if (_DayInput != null) _DayInput.IsEmpty = true; if (_MonthInput != null) _MonthInput.IsEmpty = true; if (_YearInput != null) _YearInput.IsEmpty = true; if (_HourInput != null) _HourInput.IsEmpty = true; if (_MinuteInput != null) _MinuteInput.IsEmpty = true; if (_SecondInput != null) _SecondInput.IsEmpty = true; foreach (VisualItem item in this.Items) { if (item is DateTimeGroup) ((DateTimeGroup)item).IsEmpty = true; else if (item is IDateTimePartInput && !((IDateTimePartInput)item).IsEmpty) ((IDateTimePartInput)item).IsEmpty = true; } _Value = DateTime.MinValue; } else { SetNonEmptyValue(); } } finally { _ResettingDateValue = false; } OnValueChanged(); } private System.DateTime _MinDate = MinDateTime; /// /// Gets or sets the minimum value represented by the group. /// public System.DateTime MinDate { get { return _MinDate; } set { _MinDate = value; OnMinDateChanged(); } } private void OnMinDateChanged() { UpdateInnerDateTimeGroupMinMax(); } private System.DateTime _MaxDate = MaxDateTime; /// /// Gets or sets maximum value represented by the group. /// public System.DateTime MaxDate { get { return _MaxDate; } set { _MaxDate = value; OnMaxDateChanged(); } } private void OnMaxDateChanged() { UpdateInnerDateTimeGroupMinMax(); } private void UpdateInnerDateTimeGroupMinMax() { foreach (VisualItem item in this.Items) { DateTimeGroup dg = item as DateTimeGroup; if (dg != null) { dg.MinDate = _MinDate; dg.MaxDate = _MaxDate; } } } protected override void OnAllowEmptyStateChanged() { if (!this.AllowEmptyState && this.IsEmpty) { SetNonEmptyValue(); } base.OnAllowEmptyStateChanged(); } private void SetNonEmptyValue() { if (this.MinDate > MinDateTime) this.Value = this.MinDate; else this.Value = DateTime.Now; } internal override void ProcessKeyDown(System.Windows.Forms.KeyEventArgs e) { if (e.KeyCode != System.Windows.Forms.Keys.Back && e.KeyCode != System.Windows.Forms.Keys.Delete) IsUserInput = true; base.ProcessKeyDown(e); IsUserInput = false; } internal override void ProcessKeyPress(System.Windows.Forms.KeyPressEventArgs e) { IsUserInput = true; base.ProcessKeyPress(e); IsUserInput = false; } internal override bool ProcessCmdKey(ref System.Windows.Forms.Message msg, System.Windows.Forms.Keys keyData) { IsUserInput = true; bool b = base.ProcessCmdKey(ref msg, keyData); IsUserInput = false; return b; } internal override void ProcessMouseWheel(System.Windows.Forms.MouseEventArgs e) { IsUserInput = true; base.ProcessMouseWheel(e); IsUserInput = false; } private bool _DefaultInputValues = true; /// /// Gets or sets whether input values are set to defaults while user is entering data. Default value is true. /// public bool DefaultInputValues { get { return _DefaultInputValues; } set { _DefaultInputValues = value; } } #endregion } } #endif