CalendarDayButton.cs 8.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238
  1. // (c) Copyright Microsoft Corporation.
  2. // This source is subject to the Microsoft Public License (Ms-PL).
  3. // Please see http://go.microsoft.com/fwlink/?LinkID=131993 for details.
  4. // All other rights reserved.
  5. using System;
  6. using System.Globalization;
  7. using Avalonia.Input;
  8. namespace Avalonia.Controls.Primitives
  9. {
  10. public sealed class CalendarDayButton : Button
  11. {
  12. /// <summary>
  13. /// Default content for the CalendarDayButton.
  14. /// </summary>
  15. private const int DefaultContent = 1;
  16. private bool _isCurrent;
  17. private bool _ignoringMouseOverState;
  18. private bool _isBlackout;
  19. private bool _isToday;
  20. private bool _isInactive;
  21. private bool _isSelected;
  22. /// <summary>
  23. /// Initializes a new instance of the
  24. /// <see cref="T:Avalonia.Controls.Primitives.CalendarDayButton" />
  25. /// class.
  26. /// </summary>
  27. public CalendarDayButton()
  28. : base()
  29. {
  30. //Focusable = false;
  31. Content = DefaultContent.ToString(CultureInfo.CurrentCulture);
  32. }
  33. /// <summary>
  34. /// Gets or sets the Calendar associated with this button.
  35. /// </summary>
  36. internal Calendar Owner { get; set; }
  37. internal int Index { get; set; }
  38. /// <summary>
  39. /// Gets or sets a value indicating whether the button is the focused
  40. /// element on the Calendar control.
  41. /// </summary>
  42. internal bool IsCurrent
  43. {
  44. get { return _isCurrent; }
  45. set
  46. {
  47. if (_isCurrent != value)
  48. {
  49. _isCurrent = value;
  50. SetPseudoClasses();
  51. }
  52. }
  53. }
  54. /// <summary>
  55. /// Ensure the button is not in the MouseOver state.
  56. /// </summary>
  57. /// <remarks>
  58. /// If a button is in the MouseOver state when a Popup is closed (as is
  59. /// the case when you select a date in the DatePicker control), it will
  60. /// continue to think it's in the mouse over state even when the Popup
  61. /// opens again and it's not. This method is used to forcibly clear the
  62. /// state by changing the CommonStates state group.
  63. /// </remarks>
  64. internal void IgnoreMouseOverState()
  65. {
  66. // TODO: Investigate whether this needs to be done by changing the
  67. // state everytime we change any state, or if it can be done once
  68. // to properly reset the control.
  69. _ignoringMouseOverState = false;
  70. // If the button thinks it's in the MouseOver state (which can
  71. // happen when a Popup is closed before the button can change state)
  72. // we will override the state so it shows up as normal.
  73. if (IsPointerOver)
  74. {
  75. _ignoringMouseOverState = true;
  76. SetPseudoClasses();
  77. }
  78. }
  79. /// <summary>
  80. /// Gets or sets a value indicating whether this is a blackout date.
  81. /// </summary>
  82. internal bool IsBlackout
  83. {
  84. get { return _isBlackout; }
  85. set
  86. {
  87. if (_isBlackout != value)
  88. {
  89. _isBlackout = value;
  90. SetPseudoClasses();
  91. }
  92. }
  93. }
  94. /// <summary>
  95. /// Gets or sets a value indicating whether this button represents
  96. /// today.
  97. /// </summary>
  98. internal bool IsToday
  99. {
  100. get { return _isToday; }
  101. set
  102. {
  103. if (_isToday != value)
  104. {
  105. _isToday = value;
  106. SetPseudoClasses();
  107. }
  108. }
  109. }
  110. /// <summary>
  111. /// Gets or sets a value indicating whether the button is inactive.
  112. /// </summary>
  113. internal bool IsInactive
  114. {
  115. get { return _isInactive; }
  116. set
  117. {
  118. if (_isInactive != value)
  119. {
  120. _isInactive = value;
  121. SetPseudoClasses();
  122. }
  123. }
  124. }
  125. /// <summary>
  126. /// Gets or sets a value indicating whether the button is selected.
  127. /// </summary>
  128. internal bool IsSelected
  129. {
  130. get { return _isSelected; }
  131. set
  132. {
  133. if (_isSelected != value)
  134. {
  135. _isSelected = value;
  136. SetPseudoClasses();
  137. }
  138. }
  139. }
  140. protected override void OnApplyTemplate(TemplateAppliedEventArgs e)
  141. {
  142. SetPseudoClasses();
  143. }
  144. private void SetPseudoClasses()
  145. {
  146. if (_ignoringMouseOverState)
  147. {
  148. PseudoClasses.Set(":pressed", IsPressed);
  149. PseudoClasses.Set(":disabled", !IsEnabled);
  150. }
  151. PseudoClasses.Set(":selected", IsSelected);
  152. PseudoClasses.Set(":inactive", IsInactive);
  153. PseudoClasses.Set(":today", IsToday);
  154. PseudoClasses.Set(":blackout", IsBlackout);
  155. PseudoClasses.Set(":dayfocused", IsCurrent && IsEnabled);
  156. }
  157. /// <summary>
  158. /// Occurs when the left mouse button is pressed (or when the tip of the
  159. /// stylus touches the tablet PC) while the mouse pointer is over a
  160. /// UIElement.
  161. /// </summary>
  162. public event EventHandler<PointerPressedEventArgs> CalendarDayButtonMouseDown;
  163. /// <summary>
  164. /// Occurs when the left mouse button is released (or the tip of the
  165. /// stylus is removed from the tablet PC) while the mouse (or the
  166. /// stylus) is over a UIElement (or while a UIElement holds mouse
  167. /// capture).
  168. /// </summary>
  169. public event EventHandler<PointerReleasedEventArgs> CalendarDayButtonMouseUp;
  170. /// <summary>
  171. /// Provides class handling for the MouseLeftButtonDown event that
  172. /// occurs when the left mouse button is pressed while the mouse pointer
  173. /// is over this control.
  174. /// </summary>
  175. /// <param name="e">The event data. </param>
  176. /// <exception cref="System.ArgumentNullException">
  177. /// e is a null reference (Nothing in Visual Basic).
  178. /// </exception>
  179. /// <remarks>
  180. /// This method marks the MouseLeftButtonDown event as handled by
  181. /// setting the MouseButtonEventArgs.Handled property of the event data
  182. /// to true when the button is enabled and its ClickMode is not set to
  183. /// Hover. Since this method marks the MouseLeftButtonDown event as
  184. /// handled in some situations, you should use the Click event instead
  185. /// to detect a button click.
  186. /// </remarks>
  187. protected override void OnPointerPressed(PointerPressedEventArgs e)
  188. {
  189. base.OnPointerPressed(e);
  190. if (e.GetCurrentPoint(this).Properties.IsLeftButtonPressed)
  191. CalendarDayButtonMouseDown?.Invoke(this, e);
  192. }
  193. /// <summary>
  194. /// Provides handling for the MouseLeftButtonUp event that occurs when
  195. /// the left mouse button is released while the mouse pointer is over
  196. /// this control.
  197. /// </summary>
  198. /// <param name="e">The event data.</param>
  199. /// <exception cref="System.ArgumentNullException">
  200. /// e is a null reference (Nothing in Visual Basic).
  201. /// </exception>
  202. /// <remarks>
  203. /// This method marks the MouseLeftButtonUp event as handled by setting
  204. /// the MouseButtonEventArgs.Handled property of the event data to true
  205. /// when the button is enabled and its ClickMode is not set to Hover.
  206. /// Since this method marks the MouseLeftButtonUp event as handled in
  207. /// some situations, you should use the Click event instead to detect a
  208. /// button click.
  209. /// </remarks>
  210. protected override void OnPointerReleased(PointerReleasedEventArgs e)
  211. {
  212. base.OnPointerReleased(e);
  213. if (e.InitialPressMouseButton == MouseButton.Left)
  214. CalendarDayButtonMouseUp?.Invoke(this, e);
  215. }
  216. }
  217. }