[LoongArch64] Part-5:add loongarch support in some files for LoongArch64. (#21769)
[mono-project.git] / mcs / class / System.Windows.Forms / System.Windows.Forms / DateTimePicker.cs
blob4d230582cf4cde6f673653d81187e2ebc7389cb3
1 // Permission is hereby granted, free of charge, to any person obtaining
2 // a copy of this software and associated documentation files (the
3 // "Software"), to deal in the Software without restriction, including
4 // without limitation the rights to use, copy, modify, merge, publish,
5 // distribute, sublicense, and/or sell copies of the Software, and to
6 // permit persons to whom the Software is furnished to do so, subject to
7 // the following conditions:
8 //
9 // The above copyright notice and this permission notice shall be
10 // included in all copies or substantial portions of the Software.
11 //
12 // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
13 // EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
14 // MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
15 // NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
16 // LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
17 // OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
18 // WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
20 // Copyright (c) 2004-2005 Novell, Inc.
22 // Authors:
23 // John BouAntoun jba-mono@optusnet.com.au
24 // Rolf Bjarne Kvinge rolfkvinge@ya.com
26 // TODO:
27 // - wire in all events from monthcalendar
30 using System;
31 using System.Drawing;
32 using System.Collections;
33 using System.ComponentModel;
34 using System.Globalization;
35 using System.Runtime.InteropServices;
36 using System.Windows.Forms;
38 namespace System.Windows.Forms {
39 [ClassInterface (ClassInterfaceType.AutoDispatch)]
40 [DefaultBindingProperty ("Value")]
41 [ComVisible (true)]
42 [DefaultEvent("ValueChanged")]
43 [DefaultProperty("Value")]
44 [Designer("System.Windows.Forms.Design.DateTimePickerDesigner, " + Consts.AssemblySystem_Design, "System.ComponentModel.Design.IDesigner")]
45 public class DateTimePicker : Control {
47 #region Public variables
49 // this class has to have the specified hour, minute and second, as it says in msdn
50 [EditorBrowsable (EditorBrowsableState.Never)]
51 [Browsable (false)]
52 public static readonly DateTime MaxDateTime = new DateTime (9998, 12, 31, 0, 0, 0);
54 [EditorBrowsable (EditorBrowsableState.Never)]
55 [Browsable (false)]
56 public static readonly DateTime MinDateTime = new DateTime (1753, 1, 1);
58 internal const int check_box_size = 13;
59 internal const int check_box_space = 4;
61 #endregion // Public variables
63 #region Local variables
65 protected static readonly Color DefaultMonthBackColor = ThemeEngine.Current.ColorWindow;
66 protected static readonly Color DefaultTitleBackColor = ThemeEngine.Current.ColorActiveCaption;
67 protected static readonly Color DefaultTitleForeColor = ThemeEngine.Current.ColorActiveCaptionText;
68 protected static readonly Color DefaultTrailingForeColor = SystemColors.GrayText;
70 internal MonthCalendar month_calendar;
71 bool is_checked;
72 string custom_format;
73 LeftRightAlignment drop_down_align;
74 DateTimePickerFormat format;
75 DateTime max_date;
76 DateTime min_date;
77 bool show_check_box;
78 bool show_up_down;
79 DateTime date_value;
80 bool right_to_left_layout;
82 // variables used for drawing and such
83 internal const int up_down_width = check_box_size;
84 internal bool is_drop_down_visible;
85 internal bool is_up_pressed;
86 internal bool is_down_pressed;
87 internal Timer updown_timer;
88 internal const int initial_timer_delay = 500;
89 internal const int subsequent_timer_delay = 100;
90 internal bool is_checkbox_selected;
92 // variables for determining how to format the string
93 internal PartData[] part_data;
94 internal int editing_part_index = -1;
95 internal int editing_number = -1;
96 internal string editing_text;
98 bool drop_down_button_entered;
99 #endregion // Local variables
101 #region DateTimePickerAccessibleObject Subclass
102 [ComVisible(true)]
103 public class DateTimePickerAccessibleObject : ControlAccessibleObject {
104 #region DateTimePickerAccessibleObject Local Variables
105 private new DateTimePicker owner;
106 #endregion // DateTimePickerAccessibleObject Local Variables
108 #region DateTimePickerAccessibleObject Constructors
109 public DateTimePickerAccessibleObject(DateTimePicker owner) : base(owner) {
110 this.owner = owner;
112 #endregion // DateTimePickerAccessibleObject Constructors
114 #region DateTimePickerAccessibleObject Properties
115 public override string KeyboardShortcut {
116 get {
117 return base.KeyboardShortcut;
121 public override AccessibleRole Role {
122 get {
123 return base.Role;
127 public override AccessibleStates State {
128 get {
129 AccessibleStates retval;
131 retval = AccessibleStates.Default;
133 if (owner.Checked) {
134 retval |= AccessibleStates.Checked;
137 return retval;
141 public override string Value {
142 get {
143 return owner.Text;
146 #endregion // DateTimePickerAccessibleObject Properties
148 #endregion // DateTimePickerAccessibleObject Sub-class
150 #region public constructors
152 // only public constructor
153 public DateTimePicker () {
155 // initialise the month calendar
156 month_calendar = new MonthCalendar (this);
157 month_calendar.CalendarDimensions = new Size (1, 1);
158 month_calendar.MaxSelectionCount = 1;
159 month_calendar.ForeColor = Control.DefaultForeColor;
160 month_calendar.BackColor = DefaultMonthBackColor;
161 month_calendar.TitleBackColor = DefaultTitleBackColor;
162 month_calendar.TitleForeColor = DefaultTitleForeColor;
163 month_calendar.TrailingForeColor = DefaultTrailingForeColor;
164 month_calendar.Visible = false;
165 // initialize the timer
166 updown_timer = new Timer();
167 updown_timer.Interval = initial_timer_delay;
170 // initialise other variables
171 is_checked = true;
172 custom_format = null;
173 drop_down_align = LeftRightAlignment.Left;
174 format = DateTimePickerFormat.Long;
175 max_date = MaxDateTime;
176 min_date = MinDateTime;
177 show_check_box = false;
178 show_up_down = false;
179 date_value = DateTime.Now;
181 is_drop_down_visible = false;
182 BackColor = SystemColors.Window;
183 ForeColor = SystemColors.WindowText;
185 month_calendar.DateChanged += new DateRangeEventHandler (MonthCalendarDateChangedHandler);
186 month_calendar.DateSelected += new DateRangeEventHandler (MonthCalendarDateSelectedHandler);
187 month_calendar.LostFocus += new EventHandler (MonthCalendarLostFocusHandler);
188 updown_timer.Tick += new EventHandler (UpDownTimerTick);
189 KeyPress += new KeyPressEventHandler (KeyPressHandler);
190 KeyDown += new KeyEventHandler (KeyDownHandler);
191 GotFocus += new EventHandler (GotFocusHandler);
192 LostFocus += new EventHandler (LostFocusHandler);
193 MouseDown += new MouseEventHandler (MouseDownHandler);
194 MouseUp += new MouseEventHandler (MouseUpHandler);
195 MouseEnter += new EventHandler (OnMouseEnter);
196 MouseLeave += new EventHandler (OnMouseLeave);
197 MouseMove += new MouseEventHandler (OnMouseMove);
198 Paint += new PaintEventHandler (PaintHandler);
199 Resize += new EventHandler (ResizeHandler);
200 SetStyle (ControlStyles.UserPaint | ControlStyles.StandardClick, false);
201 SetStyle (ControlStyles.FixedHeight, true);
202 SetStyle (ControlStyles.Selectable, true);
204 CalculateFormats ();
207 #endregion
209 #region public properties
211 [Browsable(false)]
212 [EditorBrowsable(EditorBrowsableState.Never)]
213 public override Color BackColor {
214 set {
215 base.BackColor = value;
217 get {
218 return base.BackColor;
222 [Browsable(false)]
223 [EditorBrowsable(EditorBrowsableState.Never)]
224 public override Image BackgroundImage {
225 set {
226 base.BackgroundImage = value;
228 get {
229 return base.BackgroundImage;
233 [Browsable (false)]
234 [EditorBrowsable (EditorBrowsableState.Never)]
235 public override ImageLayout BackgroundImageLayout {
236 get{
237 return base.BackgroundImageLayout;
239 set {
240 base.BackgroundImageLayout = value;
244 [AmbientValue(null)]
245 [Localizable(true)]
246 public Font CalendarFont {
247 set {
248 month_calendar.Font = value;
250 get {
251 return month_calendar.Font;
255 public Color CalendarForeColor {
256 set {
257 month_calendar.ForeColor = value;
259 get {
260 return month_calendar.ForeColor;
264 public Color CalendarMonthBackground {
265 set {
266 month_calendar.BackColor = value;
268 get {
269 return month_calendar.BackColor;
273 public Color CalendarTitleBackColor {
274 set {
275 month_calendar.TitleBackColor = value;
277 get {
278 return month_calendar.TitleBackColor;
282 public Color CalendarTitleForeColor {
283 set {
284 month_calendar.TitleForeColor = value;
286 get {
287 return month_calendar.TitleForeColor;
291 public Color CalendarTrailingForeColor {
292 set {
293 month_calendar.TrailingForeColor = value;
295 get {
296 return month_calendar.TrailingForeColor;
300 // when checked the value is grayed out
301 [Bindable(true)]
302 [DefaultValue(true)]
303 public bool Checked {
304 set {
305 if (is_checked != value) {
306 is_checked = value;
307 // invalidate the value inside this control
308 if (ShowCheckBox) {
309 for (int i = 0; i < part_data.Length; i++)
310 part_data [i].Selected = false;
311 Invalidate (date_area_rect);
312 OnUIAChecked ();
313 OnUIASelectionChanged ();
317 get {
318 return is_checked;
322 // the custom format string to format this control with
323 [Localizable (true)]
324 [DefaultValue(null)]
325 [RefreshProperties(RefreshProperties.Repaint)]
326 public string CustomFormat {
327 set {
328 if (custom_format != value) {
329 custom_format = value;
330 if (this.Format == DateTimePickerFormat.Custom) {
331 CalculateFormats ();
335 get {
336 return custom_format;
340 [EditorBrowsable (EditorBrowsableState.Never)]
341 protected override bool DoubleBuffered {
342 get {
343 return base.DoubleBuffered;
345 set {
346 base.DoubleBuffered = value;
350 // which side the drop down is to be aligned on
351 [DefaultValue(LeftRightAlignment.Left)]
352 [Localizable(true)]
353 public LeftRightAlignment DropDownAlign {
354 set {
355 if (drop_down_align != value) {
356 drop_down_align = value;
359 get {
360 return drop_down_align;
364 [Browsable(false)]
365 [EditorBrowsable(EditorBrowsableState.Never)]
366 public override Color ForeColor {
367 set {
368 base.ForeColor = value;
370 get {
371 return base.ForeColor;
375 // the format of the date time picker text, default is long
376 [RefreshProperties(RefreshProperties.Repaint)]
377 public DateTimePickerFormat Format {
378 set {
379 if (format != value) {
380 format = value;
381 RecreateHandle (); // MS recreates the handle on every format change.
382 CalculateFormats ();
383 this.OnFormatChanged (EventArgs.Empty);
384 // invalidate the value inside this control
385 this.Invalidate (date_area_rect);
388 get {
389 return format;
393 public DateTime MaxDate {
394 set {
395 if (value < min_date) {
396 string msg = string.Format (CultureInfo.CurrentCulture,
397 "'{0}' is not a valid value for 'MaxDate'. 'MaxDate' "
398 + "must be greater than or equal to MinDate.",
399 value.ToString ("G"));
400 throw new ArgumentOutOfRangeException ("MaxDate", msg);
402 if (value > MaxDateTime) {
403 string msg = string.Format (CultureInfo.CurrentCulture,
404 "DateTimePicker does not support dates after {0}.",
405 MaxDateTime.ToString ("G", CultureInfo.CurrentCulture));
406 throw new ArgumentOutOfRangeException ("MaxDate", msg);
408 if (max_date != value) {
409 max_date = value;
410 if (Value > max_date) {
411 Value = max_date;
412 // invalidate the value inside this control
413 this.Invalidate (date_area_rect);
415 OnUIAMaximumChanged ();
418 get {
419 return max_date;
423 public static DateTime MaximumDateTime {
424 get {
425 return MaxDateTime;
429 public DateTime MinDate {
430 set {
431 // If the user tries to set DateTime.MinValue, fix it to
432 // DateTimePicker's minimum.
433 if (value == DateTime.MinValue)
434 value = MinDateTime;
436 if (value > MaxDate) {
437 string msg = string.Format (CultureInfo.CurrentCulture,
438 "'{0}' is not a valid value for 'MinDate'. 'MinDate' "
439 + "must be less than MaxDate.",
440 value.ToString ("G"));
441 throw new ArgumentOutOfRangeException ("MinDate", msg);
443 if (value < MinDateTime) {
444 string msg = string.Format (CultureInfo.CurrentCulture,
445 "DateTimePicker does not support dates before {0}.",
446 MinDateTime.ToString ("G", CultureInfo.CurrentCulture));
447 throw new ArgumentOutOfRangeException ("MinDate", msg);
449 if (min_date != value) {
450 min_date = value;
451 if (Value < min_date) {
452 Value = min_date;
453 // invalidate the value inside this control
454 this.Invalidate (date_area_rect);
456 OnUIAMinimumChanged ();
459 get {
460 return min_date;
464 public static DateTime MinimumDateTime {
465 get {
466 return MinDateTime;
470 [EditorBrowsable (EditorBrowsableState.Never)]
471 [DesignerSerializationVisibility (DesignerSerializationVisibility.Hidden)]
472 [Browsable (false)]
473 public new Padding Padding {
474 get { return base.Padding; }
475 set { base.Padding = value; }
478 // the prefered height to draw this control using current font
479 [Browsable(false)]
480 [DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden)]
481 public int PreferredHeight {
482 get {
483 // Make it proportional
484 return (int) Math.Ceiling (Font.Height * 1.5);
488 [DefaultValue (false)]
489 [Localizable (true)]
490 public virtual bool RightToLeftLayout {
491 get {
492 return right_to_left_layout;
494 set {
495 if (right_to_left_layout != value) {
496 right_to_left_layout = value;
497 OnRightToLeftLayoutChanged (EventArgs.Empty);
502 // whether or not the check box is shown
503 [DefaultValue(false)]
504 public bool ShowCheckBox {
505 set {
506 if (show_check_box != value) {
507 show_check_box = value;
508 // invalidate the value inside this control
509 this.Invalidate (date_area_rect);
510 OnUIAShowCheckBoxChanged ();
513 get {
514 return show_check_box;
518 // if true show the updown control, else popup the monthcalendar
519 [DefaultValue(false)]
520 public bool ShowUpDown {
521 set {
522 if (show_up_down != value) {
523 show_up_down = value;
524 // need to invalidate the whole control
525 this.Invalidate ();
526 OnUIAShowUpDownChanged ();
529 get {
530 return show_up_down;
534 [Browsable(false)]
535 [EditorBrowsable(EditorBrowsableState.Advanced)]
536 [DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden)]
537 public override string Text {
538 set {
539 DateTime parsed_value;
541 if (value == null || value == string.Empty) {
542 date_value = DateTime.Now;
543 OnValueChanged (EventArgs.Empty);
544 OnTextChanged (EventArgs.Empty);
545 return;
548 if (format == DateTimePickerFormat.Custom) {
549 // TODO: if the format is a custom format we need to do a custom parse here
550 // This implementation will fail if the custom format is set to something that can
551 // be a standard datetime format string
552 // http://msdn2.microsoft.com/en-us/library/az4se3k1.aspx
553 parsed_value = DateTime.ParseExact (value, GetExactFormat (), null);
554 } else {
555 parsed_value = DateTime.ParseExact (value, GetExactFormat (), null);
558 if (date_value != parsed_value) {
559 Value = parsed_value;
562 get {
563 if (!IsHandleCreated)
564 return "";
566 if (format == DateTimePickerFormat.Custom) {
567 System.Text.StringBuilder result = new System.Text.StringBuilder ();
568 for (int i = 0; i < part_data.Length; i++) {
569 result.Append(part_data[i].GetText(date_value));
571 return result.ToString ();
572 } else {
573 return Value.ToString (GetExactFormat ());
578 [Bindable(true)]
579 [RefreshProperties(RefreshProperties.All)]
580 public DateTime Value {
581 set {
582 if (date_value != value) {
583 if (value < MinDate || value > MaxDate)
584 throw new ArgumentOutOfRangeException ("value", "value must be between MinDate and MaxDate");
586 date_value = value;
587 this.OnValueChanged (EventArgs.Empty);
588 this.Invalidate (date_area_rect);
591 get {
592 return date_value;
596 #endregion // public properties
598 #region public methods
600 // just return the text value
601 public override string ToString () {
602 return this.Text;
605 #endregion // public methods
607 #region public events
608 static object CloseUpEvent = new object ();
609 static object DropDownEvent = new object ();
610 static object FormatChangedEvent = new object ();
611 static object ValueChangedEvent = new object ();
612 static object RightToLeftLayoutChangedEvent = new object ();
614 // raised when the monthcalendar is closed
615 public event EventHandler CloseUp {
616 add { Events.AddHandler (CloseUpEvent, value); }
617 remove { Events.RemoveHandler (CloseUpEvent, value); }
620 // raised when the monthcalendar is opened
621 public event EventHandler DropDown {
622 add { Events.AddHandler (DropDownEvent, value); }
623 remove { Events.RemoveHandler (DropDownEvent, value); }
626 // raised when the format of the value is changed
627 public event EventHandler FormatChanged {
628 add { Events.AddHandler (FormatChangedEvent, value); }
629 remove { Events.RemoveHandler (FormatChangedEvent, value); }
632 // raised when the date Value is changed
633 public event EventHandler ValueChanged {
634 add { Events.AddHandler (ValueChangedEvent, value); }
635 remove { Events.RemoveHandler (ValueChangedEvent, value); }
638 [Browsable(false)]
639 [EditorBrowsable(EditorBrowsableState.Never)]
640 public new event EventHandler BackColorChanged {
641 add {
642 base.BackColorChanged += value;
645 remove {
646 base.BackColorChanged -= value;
650 [Browsable(false)]
651 [EditorBrowsable(EditorBrowsableState.Never)]
652 public new event EventHandler BackgroundImageChanged {
653 add {
654 base.BackgroundImageChanged += value;
657 remove {
658 base.BackgroundImageChanged -= value;
662 [Browsable (false)]
663 [EditorBrowsable (EditorBrowsableState.Never)]
664 public new event EventHandler BackgroundImageLayoutChanged {
667 base.BackgroundImageLayoutChanged += value;
670 remove
672 base.BackgroundImageLayoutChanged -= value;
676 [Browsable (false)]
677 [EditorBrowsable (EditorBrowsableState.Never)]
678 public new event EventHandler Click {
679 add {
680 base.Click += value;
682 remove {
683 base.Click -= value;
687 [Browsable (false)]
688 [EditorBrowsable (EditorBrowsableState.Never)]
689 public new event EventHandler DoubleClick {
690 add {
691 base.DoubleClick += value;
693 remove {
694 base.DoubleClick -= value;
698 [Browsable(false)]
699 [EditorBrowsable(EditorBrowsableState.Never)]
700 public new event EventHandler ForeColorChanged {
701 add {
702 base.ForeColorChanged += value;
705 remove {
706 base.ForeColorChanged -= value;
710 [Browsable (false)]
711 [EditorBrowsable (EditorBrowsableState.Never)]
712 public new event MouseEventHandler MouseClick {
713 add {
714 base.MouseClick += value;
716 remove {
717 base.MouseClick -= value;
721 [Browsable (false)]
722 [EditorBrowsable (EditorBrowsableState.Never)]
723 public new event MouseEventHandler MouseDoubleClick {
724 add {
725 base.MouseDoubleClick += value;
727 remove {
728 base.MouseDoubleClick -= value;
732 [Browsable (false)]
733 [EditorBrowsable (EditorBrowsableState.Never)]
734 public new event EventHandler PaddingChanged {
737 base.PaddingChanged += value;
739 remove
741 base.PaddingChanged -= value;
745 [Browsable(false)]
746 [EditorBrowsable(EditorBrowsableState.Never)]
747 public new event PaintEventHandler Paint {
748 add {
749 base.Paint += value;
752 remove {
753 base.Paint -= value;
757 public event EventHandler RightToLeftLayoutChanged {
758 add {
759 Events.AddHandler (RightToLeftLayoutChangedEvent, value);
761 remove {
762 Events.RemoveHandler (RightToLeftLayoutChangedEvent, value);
766 [Browsable(false)]
767 [EditorBrowsable(EditorBrowsableState.Advanced)]
768 public new event EventHandler TextChanged {
769 add {
770 base.TextChanged += value;
773 remove {
774 base.TextChanged -= value;
777 #endregion // public events
779 #region protected properties
781 // not sure why we're overriding this one
782 protected override CreateParams CreateParams {
783 get {
784 return base.CreateParams;
788 // specify the default size for this control
789 protected override Size DefaultSize {
790 get {
791 // todo actually measure this properly
792 return new Size (200, PreferredHeight);
796 #endregion // protected properties
798 #region protected methods
800 // not sure why we're overriding this one
801 protected override AccessibleObject CreateAccessibilityInstance () {
802 return base.CreateAccessibilityInstance ();
805 // not sure why we're overriding this one
806 protected override void CreateHandle () {
807 base.CreateHandle ();
810 // not sure why we're overriding this one
811 protected override void DestroyHandle () {
812 base.DestroyHandle ();
815 // find out if this key is an input key for us, depends on which date part is focused
816 protected override bool IsInputKey (Keys keyData) {
817 switch (keyData)
819 case Keys.Up:
820 case Keys.Down:
821 case Keys.Left:
822 case Keys.Right:
823 return true;
825 return false;
828 // raises the CloseUp event
829 protected virtual void OnCloseUp (EventArgs eventargs) {
830 EventHandler eh = (EventHandler)(Events [CloseUpEvent]);
831 if (eh != null)
832 eh (this, eventargs);
835 // raise the drop down event
836 protected virtual void OnDropDown (EventArgs eventargs) {
837 EventHandler eh = (EventHandler)(Events [DropDownEvent]);
838 if (eh != null)
839 eh (this, eventargs);
842 protected override void OnFontChanged(EventArgs e) {
843 // FIXME - do we need to update/invalidate/recalc our stuff?
844 month_calendar.Font = Font;
845 Size = new Size (Size.Width, PreferredHeight);
847 base.OnFontChanged (e);
850 // raises the format changed event
851 protected virtual void OnFormatChanged (EventArgs e) {
852 EventHandler eh = (EventHandler)(Events [FormatChangedEvent]);
853 if (eh != null)
854 eh (this, e);
857 protected override void OnHandleCreated (EventArgs e) {
858 base.OnHandleCreated(e);
860 protected override void OnHandleDestroyed (EventArgs e) {
861 base.OnHandleDestroyed(e);
864 [EditorBrowsable (EditorBrowsableState.Advanced)]
865 protected virtual void OnRightToLeftLayoutChanged (EventArgs e) {
866 EventHandler eh = (EventHandler) Events [RightToLeftLayoutChangedEvent];
867 if (eh != null)
868 eh (this, e);
871 // not sure why we're overriding this one
872 protected override void OnSystemColorsChanged (EventArgs e) {
873 base.OnSystemColorsChanged (e);
876 // raise the ValueChanged event
877 protected virtual void OnValueChanged (EventArgs eventargs) {
878 EventHandler eh = (EventHandler)(Events [ValueChangedEvent]);
879 if (eh != null)
880 eh (this, eventargs);
883 // SetBoundsCore was removed from the 2.0 public API, so
884 // I had to do this hack instead. :/
885 internal override int OverrideHeight (int height)
887 return DefaultSize.Height;
890 // not sure why we're overriding this
891 protected override void WndProc (ref Message m) {
892 base.WndProc (ref m);
895 #endregion // protected methods
897 #region internal / private properties
899 // this is the region that the date and the check box is drawn on
900 internal Rectangle date_area_rect {
901 get {
902 return ThemeEngine.Current.DateTimePickerGetDateArea (this);
906 internal Rectangle CheckBoxRect {
907 get {
908 Rectangle retval = new Rectangle (check_box_space, ClientSize.Height / 2 - check_box_size / 2,
909 check_box_size, check_box_size);
910 return retval;
914 // the rectangle for the drop down arrow
915 internal Rectangle drop_down_arrow_rect {
916 get {
917 return ThemeEngine.Current.DateTimePickerGetDropDownButtonArea (this);
921 // the part of the date that is currently hilighted
922 internal Rectangle hilight_date_area {
923 get {
924 // TODO: put hilighted part calculation in here
925 return Rectangle.Empty;
929 internal bool DropDownButtonEntered {
930 get { return drop_down_button_entered; }
933 #endregion
935 #region internal / private methods
937 private void ResizeHandler (object sender, EventArgs e)
939 Invalidate ();
942 private void UpDownTimerTick (object sender, EventArgs e)
944 if (updown_timer.Interval == initial_timer_delay)
945 updown_timer.Interval = subsequent_timer_delay;
947 if (is_down_pressed)
948 IncrementSelectedPart (-1);
949 else if (is_up_pressed)
950 IncrementSelectedPart (1);
951 else
952 updown_timer.Enabled = false;
955 // calculates the maximum width
956 internal Single CalculateMaxWidth(string format, Graphics gr, StringFormat string_format)
958 SizeF size;
959 float result = 0;
960 string text;
961 Font font = this.Font;
963 switch (format)
965 case "M":
966 case "MM":
967 case "MMM":
968 case "MMMM":
969 for (int i = 1; i <= 12; i++) {
970 text = PartData.GetText (Value.AddMonths (i), format);
971 size = gr.MeasureString (text, font, int.MaxValue, string_format);
972 result = Math.Max (result, size.Width);
974 return result;
975 case "d":
976 case "dd":
977 case "ddd":
978 case "dddd":
979 for (int i = 1; i <= 12; i++) {
980 text = PartData.GetText (Value.AddDays (i), format);
981 size = gr.MeasureString (text, font, int.MaxValue, string_format);
982 result = Math.Max (result, size.Width);
984 return result;
985 case "h":
986 case "hh":
987 for (int i = 1; i <= 12; i++) {
988 text = PartData.GetText (Value.AddHours (i), format);
989 size = gr.MeasureString (text, font, int.MaxValue, string_format);
990 result = Math.Max (result, size.Width);
992 return result;
993 case "H":
994 case "HH":
995 for (int i = 1; i <= 24; i++) {
996 text = PartData.GetText (Value.AddDays (i), format);
997 size = gr.MeasureString (text, font, int.MaxValue, string_format);
998 result = Math.Max (result, size.Width);
1000 return result;
1001 case "m":
1002 case "mm":
1003 for (int i = 1; i <= 60; i++) {
1004 text = PartData.GetText (Value.AddMinutes (i), format);
1005 size = gr.MeasureString (text, font, int.MaxValue, string_format);
1006 result = Math.Max (result, size.Width);
1008 return result;
1009 case "s":
1010 case "ss":
1011 for (int i = 1; i <= 60; i++) {
1012 text = PartData.GetText (Value.AddSeconds (i), format);
1013 size = gr.MeasureString (text, font, int.MaxValue, string_format);
1014 result = Math.Max (result, size.Width);
1016 return result;
1017 case "t":
1018 case "tt":
1019 for (int i = 1; i <= 2; i++) {
1020 text = PartData.GetText (Value.AddHours (i * 12), format);
1021 size = gr.MeasureString (text, font, int.MaxValue, string_format);
1022 result = Math.Max (result, size.Width);
1024 return result;
1025 case "y":
1026 case "yy":
1027 case "yyyy":
1028 // Actually all the allowed year values are between MinDateTime and MaxDateTime,
1029 // which are 4 digits always
1030 text = PartData.GetText (Value, format);
1031 size = gr.MeasureString (text, font, int.MaxValue, string_format);
1032 result = Math.Max (result, size.Width);
1033 return result;
1034 default:
1035 return gr.MeasureString (format, font, int.MaxValue, string_format).Width;
1039 // returns the format of the date as a string
1040 // (i.e. resolves the Format enum values to it's corresponding string format)
1041 // Why CurrentCulture and not CurrentUICulture is explained here:
1042 // http://blogs.msdn.com/michkap/archive/2007/01/11/1449754.aspx
1043 private string GetExactFormat()
1045 switch (this.format) {
1046 case DateTimePickerFormat.Long:
1047 return Threading.Thread.CurrentThread.CurrentCulture.DateTimeFormat.LongDatePattern;
1048 case DateTimePickerFormat.Short:
1049 return Threading.Thread.CurrentThread.CurrentCulture.DateTimeFormat.ShortDatePattern;
1050 case DateTimePickerFormat.Time:
1051 return Threading.Thread.CurrentThread.CurrentCulture.DateTimeFormat.LongTimePattern;
1052 case DateTimePickerFormat.Custom:
1053 return this.custom_format == null ? String.Empty : this.custom_format;
1054 default:
1055 return Threading.Thread.CurrentThread.CurrentCulture.DateTimeFormat.LongDatePattern;
1059 private void CalculateFormats()
1061 string real_format;
1062 System.Text.StringBuilder literal = new System.Text.StringBuilder ();
1063 System.Collections.ArrayList formats = new ArrayList ();
1064 bool is_literal = false;
1065 char lastch = (char) 0;
1066 char ch;
1068 real_format = GetExactFormat ();
1070 // parse the format string
1071 for (int i = 0; i < real_format.Length; i++)
1073 ch = real_format [i];
1075 if (is_literal && ch != '\'')
1077 literal.Append (ch);
1078 continue;
1081 switch (ch)
1083 case 't':
1084 case 'd':
1085 case 'h':
1086 case 'H':
1087 case 'm':
1088 case 'M':
1089 case 's':
1090 case 'y':
1091 case 'g': // Spec says nothing about g, but it seems to be treated like spaces.
1092 if (!(lastch == ch || lastch == 0) && literal.Length != 0)
1094 formats.Add (new PartData(literal.ToString (), false, this));
1095 literal.Length = 0;
1097 literal.Append (ch);
1098 break;
1099 case '\'':
1100 if (is_literal && i < real_format.Length - 1 && real_format [i + 1] == '\'') {
1101 literal.Append (ch);
1102 i++;
1103 break;
1105 if (literal.Length == 0) {
1106 is_literal = !is_literal;
1107 break;
1109 formats.Add (new PartData (literal.ToString (), is_literal, this));
1110 literal.Length = 0;
1111 is_literal = !is_literal;
1112 break;
1113 default:
1114 if (literal.Length != 0)
1116 formats.Add (new PartData(literal.ToString (), false, this));
1117 literal.Length = 0;
1119 formats.Add (new PartData (ch.ToString(), true, this));
1120 break;
1123 lastch = ch;
1125 if (literal.Length >= 0)
1126 formats.Add (new PartData (literal.ToString (), is_literal, this));
1128 part_data = new PartData [formats.Count];
1129 formats.CopyTo (part_data);
1132 private Point CalculateDropDownLocation (Rectangle parent_control_rect, Size child_size, bool align_left)
1134 // default bottom left
1135 Point location = new Point(parent_control_rect.Left + 5, parent_control_rect.Bottom);
1136 // now adjust the alignment
1137 if (!align_left) {
1138 location.X = parent_control_rect.Right - child_size.Width;
1141 Point screen_location = PointToScreen (location);
1142 Rectangle working_area = Screen.FromControl(this).WorkingArea;
1143 // now adjust if off the right side of the screen
1144 if (screen_location.X < working_area.X) {
1145 screen_location.X = working_area.X;
1147 // now adjust if it should be displayed above control
1148 if (screen_location.Y + child_size.Height > working_area.Bottom) {
1149 screen_location.Y -= (parent_control_rect.Height + child_size.Height);
1152 // since the parent of the month calendar is the form, adjust accordingly.
1153 if (month_calendar.Parent != null) {
1154 screen_location = month_calendar.Parent.PointToClient(screen_location);
1157 return screen_location;
1160 // actually draw this control
1161 internal void Draw (Rectangle clip_rect, Graphics dc)
1163 ThemeEngine.Current.DrawDateTimePicker (dc, clip_rect, this);
1166 // drop the calendar down
1167 internal void DropDownMonthCalendar ()
1169 EndDateEdit (true);
1170 // ensure the right date is set for the month_calendar
1171 month_calendar.SetDate (this.date_value);
1172 // get a rectangle that has the dimensions of the text area,
1173 // but the height of the dtp control.
1174 Rectangle align_area = this.date_area_rect;
1175 align_area.Y = this.ClientRectangle.Y;
1176 align_area.Height = this.ClientRectangle.Height;
1178 // establish the month calendar's location
1179 month_calendar.Location = CalculateDropDownLocation (
1180 align_area,
1181 month_calendar.Size,
1182 (this.DropDownAlign == LeftRightAlignment.Left));
1183 month_calendar.Show ();
1184 month_calendar.Focus ();
1185 month_calendar.Capture = true;
1187 // fire any registered events
1188 // XXX should this just call OnDropDown?
1189 EventHandler eh = (EventHandler)(Events [DropDownEvent]);
1190 if (eh != null)
1191 eh (this, EventArgs.Empty);
1194 // hide the month calendar
1195 internal void HideMonthCalendar ()
1197 this.is_drop_down_visible = false;
1198 Invalidate (drop_down_arrow_rect);
1199 month_calendar.Capture = false;
1200 if (month_calendar.Visible) {
1201 month_calendar.Hide ();
1203 Focus ();
1206 private int GetSelectedPartIndex()
1208 for (int i = 0; i < part_data.Length; i++)
1210 if (part_data[i].Selected && !part_data[i].is_literal)
1211 return i;
1213 return -1;
1216 internal void IncrementSelectedPart(int delta)
1218 int selected_index = GetSelectedPartIndex();
1220 if (selected_index == -1) {
1221 return;
1224 EndDateEdit (false);
1226 DateTimePart dt_part = part_data [selected_index].date_time_part;
1227 switch (dt_part)
1229 case DateTimePart.Day:
1230 if (delta < 0) {
1231 if (Value.Day == 1)
1232 SetPart(DateTime.DaysInMonth(Value.Year, Value.Month), dt_part);
1233 else
1234 SetPart(Value.Day + delta, dt_part);
1235 } else {
1236 if (Value.Day == DateTime.DaysInMonth(Value.Year, Value.Month))
1237 SetPart(1, dt_part);
1238 else
1239 SetPart(Value.Day + delta, dt_part) ;
1241 break;
1242 case DateTimePart.DayName:
1243 Value = Value.AddDays(delta);
1244 break;
1245 case DateTimePart.AMPMHour:
1246 case DateTimePart.Hour:
1247 SetPart(Value.Hour + delta, dt_part);
1248 break;
1249 case DateTimePart.Minutes:
1250 SetPart(Value.Minute + delta, dt_part);
1251 break;
1252 case DateTimePart.Month:
1253 SetPart (Value.Month + delta, dt_part, true);
1254 break;
1255 case DateTimePart.Seconds:
1256 SetPart(Value.Second + delta, dt_part);
1257 break;
1258 case DateTimePart.AMPMSpecifier:
1259 int hour = Value.Hour;
1260 hour = hour >= 0 && hour <= 11 ? hour + 12 : hour - 12;
1261 SetPart (hour, DateTimePart.Hour);
1262 break;
1263 case DateTimePart.Year:
1264 SetPart(Value.Year + delta, dt_part);
1265 break;
1269 internal void SelectPart (int index)
1271 is_checkbox_selected = false;
1272 for (int i = 0; i < part_data.Length; i++)
1274 part_data[i].Selected = (i == index);
1277 Invalidate ();
1278 OnUIASelectionChanged ();
1281 internal void SelectNextPart()
1283 int selected_index;
1284 if (is_checkbox_selected) {
1285 for (int i = 0; i < part_data.Length; i++)
1287 if (!part_data[i].is_literal)
1289 is_checkbox_selected = false;
1290 part_data[i].Selected = true;
1291 Invalidate();
1292 break;
1295 } else {
1296 selected_index = GetSelectedPartIndex();
1297 if (selected_index >= 0)
1298 part_data [selected_index].Selected = false;
1300 for (int i = selected_index + 1; i < part_data.Length; i++)
1302 if (!part_data[i].is_literal)
1304 part_data [i].Selected = true;
1305 Invalidate();
1306 break;
1309 if (GetSelectedPartIndex() == -1)
1310 { // if no part was found before the end, look from the beginning
1311 if (ShowCheckBox)
1313 is_checkbox_selected = true;
1314 Invalidate();
1316 else
1318 for (int i = 0; i <= selected_index; i++)
1320 if (!part_data[i].is_literal)
1322 part_data[i].Selected = true;
1323 Invalidate();
1324 break;
1331 OnUIASelectionChanged ();
1334 internal void SelectPreviousPart()
1336 if (is_checkbox_selected)
1338 for (int i = part_data.Length - 1; i >= 0; i--)
1340 if (!part_data[i].is_literal)
1342 is_checkbox_selected = false;
1343 part_data[i].Selected = true;
1344 Invalidate();
1345 break;
1349 else
1351 int selected_index = GetSelectedPartIndex();
1353 if (selected_index >= 0)
1354 part_data[selected_index].Selected = false;
1356 for (int i = selected_index - 1; i >= 0; i--)
1358 if (!part_data[i].is_literal)
1360 part_data[i].Selected = true;
1361 Invalidate();
1362 break;
1365 if (GetSelectedPartIndex() == -1)
1366 { // if no part was found before the beginning, look from the end
1367 if (ShowCheckBox)
1369 is_checkbox_selected = true;
1370 Invalidate();
1372 else
1374 for (int i = part_data.Length - 1; i >= selected_index; i--)
1376 if (!part_data[i].is_literal)
1378 part_data[i].Selected = true;
1379 Invalidate();
1380 break;
1387 OnUIASelectionChanged ();
1390 // raised by key down events.
1391 private void KeyDownHandler(object sender, KeyEventArgs e)
1393 switch (e.KeyCode)
1395 case Keys.Add:
1396 case Keys.Up:
1398 if (ShowCheckBox && Checked == false)
1399 break;
1400 IncrementSelectedPart(1);
1401 e.Handled = true;
1402 break;
1404 case Keys.Subtract:
1405 case Keys.Down:
1407 if (ShowCheckBox && Checked == false)
1408 break;
1409 IncrementSelectedPart(-1);
1410 e.Handled = true;
1411 break;
1413 case Keys.Left:
1414 {// select the next part to the left
1415 if (ShowCheckBox && Checked == false)
1416 break;
1417 SelectPreviousPart();
1418 e.Handled = true;
1419 break;
1421 case Keys.Right:
1422 {// select the next part to the right
1423 if (ShowCheckBox && Checked == false)
1424 break;
1425 SelectNextPart();
1426 e.Handled = true;
1427 break;
1429 case Keys.F4:
1430 if (!e.Alt && !is_drop_down_visible) {
1431 DropDownMonthCalendar ();
1432 e.Handled = true;
1435 break;
1439 // raised by any key down events
1440 private void KeyPressHandler (object sender, KeyPressEventArgs e)
1442 switch (e.KeyChar) {
1443 case ' ':
1444 if (show_check_box && is_checkbox_selected)
1445 Checked = !Checked;
1446 break;
1447 case '0':
1448 case '1':
1449 case '2':
1450 case '3':
1451 case '4':
1452 case '5':
1453 case '6':
1454 case '7':
1455 case '8':
1456 case '9':
1457 int number = e.KeyChar - (int) '0';
1458 int selected_index = GetSelectedPartIndex();
1459 if (selected_index == -1)
1460 break;
1461 if (!part_data[selected_index].is_numeric_format)
1462 break;
1464 DateTimePart dt_part = part_data [selected_index].date_time_part;
1465 if (editing_part_index < 0) {
1466 editing_part_index = selected_index;
1467 editing_number = 0;
1468 editing_text = String.Empty;
1471 editing_text += number.ToString ();
1472 int date_part_max_length = 0;
1474 switch (dt_part) {
1475 case DateTimePart.Day:
1476 case DateTimePart.Month:
1477 case DateTimePart.Seconds:
1478 case DateTimePart.Minutes:
1479 case DateTimePart.AMPMHour:
1480 case DateTimePart.Hour:
1481 date_part_max_length = 2;
1482 break;
1483 case DateTimePart.Year:
1484 date_part_max_length = 4;
1485 break;
1488 editing_number = editing_number * 10 + number;
1489 if (editing_text.Length >= date_part_max_length)
1490 EndDateEdit (false);
1492 Invalidate (date_area_rect);
1493 break;
1494 default:
1495 break;
1497 e.Handled = true;
1500 private void EndDateEdit (bool invalidate)
1502 if (editing_part_index == -1)
1503 return;
1505 PartData part = part_data [editing_part_index];
1506 if (part.date_time_part == DateTimePart.Year) { // Special case
1507 // Infer, like .Net does
1508 if (editing_number > 0 && editing_number < 30)
1509 editing_number += 2000;
1510 else if (editing_number >= 30 && editing_number < 100)
1511 editing_number += 1900;
1514 SetPart (editing_number, part.date_time_part);
1515 editing_part_index = editing_number = -1;
1516 editing_text = null;
1518 if (invalidate)
1519 Invalidate (date_area_rect);
1522 internal void SetPart (int value, DateTimePart dt_part)
1524 SetPart (value, dt_part, false);
1527 // set the specified part of the date to the specified value
1528 internal void SetPart (int value, DateTimePart dt_part, bool adjust)
1530 switch (dt_part)
1532 case DateTimePart.Seconds:
1533 if (value == -1)
1534 value = 59;
1535 if (value >= 0 && value <= 59)
1536 Value = new DateTime(Value.Year, Value.Month, Value.Day, Value.Hour, Value.Minute, value, Value.Millisecond);
1537 break;
1538 case DateTimePart.Minutes:
1539 if (value == -1)
1540 value = 59;
1541 if (value >= 0 && value <= 59)
1542 Value = new DateTime(Value.Year, Value.Month, Value.Day, Value.Hour, value, Value.Second, Value.Millisecond);
1543 break;
1544 case DateTimePart.AMPMHour:
1545 if (value == -1)
1546 value = 23;
1547 if (value >= 0 && value <= 23) {
1548 int prev_hour = Value.Hour;
1549 if ((prev_hour >= 12 && prev_hour <= 23) && value < 12) // Adjust to p.m.
1550 value += 12;
1551 Value = new DateTime (Value.Year, Value.Month, Value.Day, value, Value.Minute, Value.Second, Value.Millisecond);
1553 break;
1554 case DateTimePart.Hour:
1555 if (value == -1)
1556 value = 23;
1557 if (value >= 0 && value <= 23)
1558 Value = new DateTime(Value.Year, Value.Month, Value.Day, value, Value.Minute, Value.Second, Value.Millisecond);
1559 break;
1560 case DateTimePart.Day:
1561 int max_days = DateTime.DaysInMonth(Value.Year, Value.Month);
1562 if (value >= 1 && value <= 31 && value <= max_days)
1563 Value = new DateTime(Value.Year, Value.Month, value, Value.Hour, Value.Minute, Value.Second, Value.Millisecond);
1564 break;
1565 case DateTimePart.Month:
1566 DateTime date = Value;
1568 if (adjust) {
1569 if (value == 0) {
1570 date = date.AddYears (-1);
1571 value = 12;
1572 } else if (value == 13) {
1573 date = date.AddYears (1);
1574 value = 1;
1578 if (value >= 1 && value <= 12) {
1579 // if we move from say december to november with days on 31, we must
1580 // remap to the maximum number of days
1581 int days_in_new_month = DateTime.DaysInMonth (date.Year, value);
1583 if (date.Day > days_in_new_month)
1584 Value = new DateTime (date.Year, value, days_in_new_month, date.Hour, date.Minute, date.Second, date.Millisecond);
1585 else
1586 Value = new DateTime (date.Year, value, date.Day, date.Hour, date.Minute, date.Second, date.Millisecond);
1588 break;
1589 case DateTimePart.Year:
1590 if (value >= min_date.Year && value <= max_date.Year) {
1591 // if we move to a leap year, the days in month could throw an exception
1592 int days_in_new_month = DateTime.DaysInMonth (value, Value.Month);
1594 if (Value.Day > days_in_new_month)
1595 Value = new DateTime (value, Value.Month, days_in_new_month, Value.Hour, Value.Minute, Value.Second, Value.Millisecond);
1596 else
1597 Value = new DateTime (value, Value.Month, Value.Day, Value.Hour, Value.Minute, Value.Second, Value.Millisecond);
1599 break;
1603 private void GotFocusHandler (object sender, EventArgs e)
1605 if (ShowCheckBox) {
1606 is_checkbox_selected = true;
1607 Invalidate (CheckBoxRect);
1608 OnUIASelectionChanged ();
1612 // if we loose focus deselect any selected parts.
1613 private void LostFocusHandler (object sender, EventArgs e)
1615 int selected_index = GetSelectedPartIndex ();
1616 if (selected_index != -1)
1618 part_data [selected_index].Selected = false;
1619 Rectangle invalidate_rect = Rectangle.Ceiling (part_data [selected_index].drawing_rectangle);
1620 invalidate_rect.Inflate (2, 2);
1621 Invalidate (invalidate_rect);
1622 OnUIASelectionChanged ();
1624 else if (is_checkbox_selected)
1626 is_checkbox_selected = false;
1627 Invalidate (CheckBoxRect);
1628 OnUIASelectionChanged ();
1632 // if month calendar looses focus and the drop down is up, then close it
1633 private void MonthCalendarLostFocusHandler(object sender, EventArgs e)
1635 if (is_drop_down_visible && !month_calendar.Focused)
1637 //this.HideMonthCalendar();
1638 //This is handled from the monthcalender itself,
1639 //it may loose focus, but still has to be visible,
1640 //for instance when the context menu is displayed.
1645 private void MonthCalendarDateChangedHandler (object sender, DateRangeEventArgs e)
1647 if (month_calendar.Visible)
1648 this.Value = e.Start.Date.Add (this.Value.TimeOfDay);
1651 // fired when a user clicks on the month calendar to select a date
1652 private void MonthCalendarDateSelectedHandler (object sender, DateRangeEventArgs e)
1654 this.HideMonthCalendar ();
1657 private void MouseUpHandler(object sender, MouseEventArgs e)
1659 if (ShowUpDown)
1661 if (is_up_pressed || is_down_pressed)
1663 updown_timer.Enabled = false;
1664 is_up_pressed = false;
1665 is_down_pressed = false;
1666 Invalidate (drop_down_arrow_rect);
1671 // to check if the mouse has come down on this control
1672 private void MouseDownHandler (object sender, MouseEventArgs e)
1674 // Only left clicks are handled.
1675 if (e.Button != MouseButtons.Left)
1676 return;
1678 if (ShowCheckBox && CheckBoxRect.Contains(e.X, e.Y))
1680 is_checkbox_selected = true;
1681 Checked = !Checked;
1682 OnUIASelectionChanged ();
1683 return;
1686 // Deselect the checkbox only if the pointer is not on it
1687 // *and* the other parts are enabled (Checked as true)
1688 if (Checked) {
1689 is_checkbox_selected = false;
1690 OnUIASelectionChanged ();
1693 if (ShowUpDown && drop_down_arrow_rect.Contains (e.X, e.Y))
1695 if (!(ShowCheckBox && Checked == false))
1697 if (e.Y < this.Height / 2) {
1698 is_up_pressed = true;
1699 is_down_pressed = false;
1700 IncrementSelectedPart (1);
1701 } else {
1702 is_up_pressed = false;
1703 is_down_pressed = true;
1704 IncrementSelectedPart (-1);
1706 Invalidate (drop_down_arrow_rect);
1707 updown_timer.Interval = initial_timer_delay;
1708 updown_timer.Enabled = true;
1710 } else if (is_drop_down_visible == false && drop_down_arrow_rect.Contains (e.X, e.Y)) {
1711 DropDownButtonClicked ();
1712 } else {
1713 // mouse down on this control anywhere else collapses it
1714 if (is_drop_down_visible) {
1715 HideMonthCalendar ();
1717 if (!(ShowCheckBox && Checked == false))
1719 // go through the parts to see if the click is in any of them
1720 bool invalidate_afterwards = false;
1721 for (int i = 0; i < part_data.Length; i++) {
1722 bool old = part_data [i].Selected;
1724 if (part_data [i].is_literal)
1725 continue;
1727 if (part_data [i].drawing_rectangle.Contains (e.X, e.Y)) {
1728 part_data [i].Selected = true;
1729 } else
1730 part_data [i].Selected = false;
1732 if (old != part_data [i].Selected)
1733 invalidate_afterwards = true;
1735 if (invalidate_afterwards) {
1736 Invalidate ();
1737 OnUIASelectionChanged ();
1744 internal void DropDownButtonClicked ()
1746 if (!is_drop_down_visible) {
1747 is_drop_down_visible = true;
1748 if (!Checked)
1749 Checked = true;
1750 Invalidate (drop_down_arrow_rect);
1751 DropDownMonthCalendar ();
1752 } else {
1753 HideMonthCalendar ();
1757 // paint this control now
1758 private void PaintHandler (object sender, PaintEventArgs pe) {
1759 if (Width <= 0 || Height <= 0 || Visible == false)
1760 return;
1762 Draw (pe.ClipRectangle, pe.Graphics);
1765 void OnMouseEnter (object sender, EventArgs e)
1767 if (ThemeEngine.Current.DateTimePickerBorderHasHotElementStyle)
1768 Invalidate ();
1771 void OnMouseLeave (object sender, EventArgs e)
1773 drop_down_button_entered = false;
1774 if (ThemeEngine.Current.DateTimePickerBorderHasHotElementStyle)
1775 Invalidate ();
1778 void OnMouseMove (object sender, MouseEventArgs e)
1780 if (!is_drop_down_visible &&
1781 ThemeEngine.Current.DateTimePickerDropDownButtonHasHotElementStyle &&
1782 drop_down_button_entered != drop_down_arrow_rect.Contains (e.Location)) {
1783 drop_down_button_entered = !drop_down_button_entered;
1784 Invalidate (drop_down_arrow_rect);
1787 #endregion
1789 #region internal classes
1790 internal enum DateTimePart {
1791 Seconds,
1792 Minutes,
1793 AMPMHour,
1794 Hour,
1795 Day,
1796 DayName,
1797 Month,
1798 Year,
1799 AMPMSpecifier,
1800 Literal
1803 internal class PartData
1805 internal string value;
1806 internal bool is_literal;
1807 bool is_selected;
1808 internal RectangleF drawing_rectangle;
1809 internal DateTimePart date_time_part;
1810 DateTimePicker owner;
1812 internal bool is_numeric_format
1816 if (is_literal)
1817 return false;
1818 switch (value) {
1819 case "m":
1820 case "mm":
1821 case "d":
1822 case "dd":
1823 case "h":
1824 case "hh":
1825 case "H":
1826 case "HH":
1827 case "M":
1828 case "MM":
1829 case "s":
1830 case "ss":
1831 case "y":
1832 case "yy":
1833 case "yyyy":
1834 return true;
1835 case "ddd":
1836 case "dddd":
1837 return false;
1838 default:
1839 return false;
1844 internal PartData(string value, bool is_literal, DateTimePicker owner)
1846 this.value = value;
1847 this.is_literal = is_literal;
1848 this.owner = owner;
1849 date_time_part = GetDateTimePart (value);
1852 internal bool Selected {
1853 get {
1854 return is_selected;
1856 set {
1857 if (value == is_selected)
1858 return;
1860 owner.EndDateEdit (false);
1861 is_selected = value;
1865 // calculate the string to show for this data
1866 internal string GetText(DateTime date)
1868 if (is_literal) {
1869 return value;
1870 } else {
1871 return GetText (date, value);
1875 static DateTimePart GetDateTimePart (string value)
1877 switch (value) {
1878 case "s":
1879 case "ss":
1880 return DateTimePart.Seconds;
1881 case "m":
1882 case "mm":
1883 return DateTimePart.Minutes;
1884 case "h":
1885 case "hh":
1886 return DateTimePart.AMPMHour;
1887 case "H":
1888 case "HH":
1889 return DateTimePart.Hour;
1890 case "d":
1891 case "dd":
1892 return DateTimePart.Day;
1893 case "ddd":
1894 case "dddd":
1895 return DateTimePart.DayName;
1896 case "M":
1897 case "MM":
1898 case "MMMM":
1899 return DateTimePart.Month;
1900 case "y":
1901 case "yy":
1902 case "yyy":
1903 case "yyyy":
1904 return DateTimePart.Year;
1905 case "t":
1906 case "tt":
1907 return DateTimePart.AMPMSpecifier;
1910 return DateTimePart.Literal;
1913 static internal string GetText(DateTime date, string format)
1915 if (format.StartsWith ("g"))
1916 return " ";
1917 else if (format.Length == 1)
1918 return date.ToString ("%" + format);
1919 else if (format == "yyyyy" || format == "yyyyyy" || format == "yyyyyyy" || format == "yyyyyyyy")
1920 return date.ToString ("yyyy");
1921 else if (format.Length > 1)
1922 return date.ToString (format);
1923 else
1924 return string.Empty;
1928 #endregion
1930 #region UIA Framework: Methods, Properties and Events
1932 internal bool UIAIsCheckBoxSelected {
1933 get { return is_checkbox_selected; }
1936 static object UIAMinimumChangedEvent = new object ();
1937 static object UIAMaximumChangedEvent = new object ();
1938 static object UIASelectionChangedEvent = new object ();
1939 static object UIACheckedEvent = new object ();
1940 static object UIAShowCheckBoxChangedEvent = new object ();
1941 static object UIAShowUpDownChangedEvent = new object ();
1943 internal event EventHandler UIAMinimumChanged {
1944 add { Events.AddHandler (UIAMinimumChangedEvent, value); }
1945 remove { Events.RemoveHandler (UIAMinimumChangedEvent, value); }
1948 internal event EventHandler UIAMaximumChanged {
1949 add { Events.AddHandler (UIAMinimumChangedEvent, value); }
1950 remove { Events.RemoveHandler (UIAMinimumChangedEvent, value); }
1953 internal event EventHandler UIASelectionChanged {
1954 add { Events.AddHandler (UIASelectionChangedEvent, value); }
1955 remove { Events.RemoveHandler (UIASelectionChangedEvent, value); }
1958 internal event EventHandler UIAChecked {
1959 add { Events.AddHandler (UIACheckedEvent, value); }
1960 remove { Events.RemoveHandler (UIACheckedEvent, value); }
1963 internal event EventHandler UIAShowCheckBoxChanged {
1964 add { Events.AddHandler (UIAShowCheckBoxChangedEvent, value); }
1965 remove { Events.RemoveHandler (UIAShowCheckBoxChangedEvent, value); }
1968 internal event EventHandler UIAShowUpDownChanged {
1969 add { Events.AddHandler (UIAShowUpDownChangedEvent, value); }
1970 remove { Events.RemoveHandler (UIAShowUpDownChangedEvent, value); }
1973 internal void OnUIAMinimumChanged ()
1975 EventHandler eh = (EventHandler)(Events [UIAMinimumChangedEvent]);
1976 if (eh != null)
1977 eh (this, EventArgs.Empty);
1980 internal void OnUIAMaximumChanged ()
1982 EventHandler eh = (EventHandler)(Events [UIAMaximumChangedEvent]);
1983 if (eh != null)
1984 eh (this, EventArgs.Empty);
1987 internal void OnUIASelectionChanged ()
1989 EventHandler eh = (EventHandler)(Events [UIASelectionChangedEvent]);
1990 if (eh != null)
1991 eh (this, EventArgs.Empty);
1994 internal void OnUIAChecked ()
1996 EventHandler eh = (EventHandler)(Events [UIACheckedEvent]);
1997 if (eh != null)
1998 eh (this, EventArgs.Empty);
2001 internal void OnUIAShowCheckBoxChanged ()
2003 EventHandler eh = (EventHandler)(Events [UIAShowCheckBoxChangedEvent]);
2004 if (eh != null)
2005 eh (this, EventArgs.Empty);
2008 internal void OnUIAShowUpDownChanged ()
2010 EventHandler eh = (EventHandler)(Events [UIAShowUpDownChangedEvent]);
2011 if (eh != null)
2012 eh (this, EventArgs.Empty);
2015 #endregion