CoreTimeEditorControl.cs 13 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403
  1. using InABox.Core;
  2. using Syncfusion.Windows.Shared;
  3. using System;
  4. using System.Collections;
  5. using System.Collections.Generic;
  6. using System.Linq;
  7. using System.Text;
  8. using System.Threading.Tasks;
  9. using System.Windows;
  10. using System.Windows.Controls;
  11. using System.Windows.Input;
  12. using System.Windows.Media;
  13. namespace InABox.DynamicGrid
  14. {
  15. public class CoreTimeEditorControl : DynamicEnclosedEditorControl<CoreTime>
  16. {
  17. private Grid Grid;
  18. private DateTimeEdit Start;
  19. private TimeSpanEdit Duration;
  20. private DateTimeEdit Finish;
  21. private CoreTime Time = new();
  22. protected override FrameworkElement CreateEditor()
  23. {
  24. Grid = new Grid();
  25. Grid.ColumnDefinitions.Add(new ColumnDefinition { Width = GridLength.Auto });
  26. Grid.ColumnDefinitions.Add(new ColumnDefinition { Width = new GridLength(1, GridUnitType.Star) });
  27. Grid.ColumnDefinitions.Add(new ColumnDefinition { Width = GridLength.Auto });
  28. Grid.ColumnDefinitions.Add(new ColumnDefinition { Width = GridLength.Auto });
  29. Grid.ColumnDefinitions.Add(new ColumnDefinition { Width = GridLength.Auto });
  30. Grid.ColumnDefinitions.Add(new ColumnDefinition { Width = new GridLength(1, GridUnitType.Star) });
  31. Grid.ColumnDefinitions.Add(new ColumnDefinition { Width = GridLength.Auto });
  32. Grid.ColumnDefinitions.Add(new ColumnDefinition { Width = GridLength.Auto });
  33. Grid.ColumnDefinitions.Add(new ColumnDefinition { Width = GridLength.Auto });
  34. Grid.ColumnDefinitions.Add(new ColumnDefinition { Width = new GridLength(1, GridUnitType.Star) });
  35. Grid.ColumnDefinitions.Add(new ColumnDefinition { Width = GridLength.Auto });
  36. Grid.ColumnDefinitions.Add(new ColumnDefinition { Width = GridLength.Auto });
  37. Start = CreateTimeEdit("Start:", 0, StartChanged, false);
  38. Duration = CreateTimeSpanEdit("Duration:", 4, DurationChanged, true);
  39. Finish = CreateTimeEdit("Finish:", 8, FinishChanged, true);
  40. return Grid;
  41. }
  42. private void StartChanged(TimeSpan start)
  43. {
  44. Time.Start = start;
  45. UpdateEditors();
  46. }
  47. private void DurationChanged(TimeSpan duration)
  48. {
  49. Time.Duration = duration;
  50. UpdateEditors();
  51. }
  52. private void FinishChanged(TimeSpan finish)
  53. {
  54. Time.Finish = finish;
  55. UpdateEditors();
  56. }
  57. private void UpdateEditors()
  58. {
  59. SetValue(Start, Time.Start);
  60. SetValue(Duration, Time.Duration);
  61. SetValue(Finish, Time.Finish);
  62. CheckChanged();
  63. }
  64. private TimeSpanEdit CreateTimeSpanEdit(string header, int column, Action<TimeSpan> onChanged, bool leftMargin)
  65. {
  66. var label = new Label
  67. {
  68. Content = header,
  69. Margin = new Thickness(leftMargin ? 5 : 0, 0, 0, 0)
  70. };
  71. label.SetValue(Grid.ColumnProperty, column);
  72. var edit = new TimeSpanEdit
  73. {
  74. Format = "h:mm",
  75. MinValue = new TimeSpan(),
  76. MaxValue = TimeSpan.MaxValue,
  77. VerticalAlignment = VerticalAlignment.Stretch,
  78. VerticalContentAlignment = VerticalAlignment.Center,
  79. HorizontalAlignment = HorizontalAlignment.Stretch,
  80. HorizontalContentAlignment = HorizontalAlignment.Center,
  81. ShowArrowButtons = false
  82. };
  83. edit.SetValue(Grid.ColumnProperty, column + 1);
  84. edit.PreviewKeyDown += (o, e) =>
  85. {
  86. var separator = edit.Text.IndexOf(":");
  87. if (e.Key == Key.OemPeriod)
  88. {
  89. edit.Select(separator + 1, 2);
  90. e.Handled = true;
  91. }
  92. else if (e.Key == Key.Back)
  93. {
  94. if (string.Equals(edit.SelectedText, "00"))
  95. edit.Select(0, separator);
  96. else
  97. edit.SelectedText = "00";
  98. e.Handled = true;
  99. }
  100. else if (e.Key == Key.Tab)
  101. {
  102. if (Keyboard.IsKeyDown(Key.LeftShift) || Keyboard.IsKeyDown(Key.LeftShift))
  103. {
  104. if (edit.SelectionStart > separator)
  105. {
  106. edit.Select(0, separator);
  107. e.Handled = true;
  108. }
  109. }
  110. else
  111. {
  112. if (edit.SelectionLength != edit.Text.Length && edit.SelectionStart < separator)
  113. {
  114. edit.Select(separator + 1, 2);
  115. e.Handled = true;
  116. }
  117. }
  118. }
  119. };
  120. var changed = false;
  121. edit.ValueChanged += (o, e) =>
  122. {
  123. changed = true;
  124. };
  125. edit.LostFocus += (o, e) =>
  126. {
  127. if (changed)
  128. onChanged(GetValue(edit));
  129. };
  130. var less = new Button
  131. {
  132. Content = "<",
  133. Width = 23,
  134. Margin = new Thickness(2, 0, 0, 0),
  135. Focusable = false
  136. };
  137. less.SetValue(Grid.ColumnProperty, column + 2);
  138. less.Click += (o, e) =>
  139. {
  140. edit.Value = edit.Value.HasValue && edit.Value >= new TimeSpan(0, 15, 0)
  141. ? edit.Value.Value.Subtract(new TimeSpan(0, 15, 0))
  142. : new TimeSpan(0);
  143. onChanged(GetValue(edit));
  144. };
  145. var more = new Button
  146. {
  147. Content = ">",
  148. Width = 23,
  149. Margin = new Thickness(2, 0, 0, 0),
  150. Focusable = false
  151. };
  152. more.SetValue(Grid.ColumnProperty, column + 3);
  153. more.Click += (o, e) =>
  154. {
  155. edit.Value = edit.Value.HasValue ? edit.Value.Value.Add(new TimeSpan(0, 15, 0)) : new TimeSpan(0, 15, 0);
  156. onChanged(GetValue(edit));
  157. };
  158. Grid.Children.Add(label);
  159. Grid.Children.Add(more);
  160. Grid.Children.Add(less);
  161. Grid.Children.Add(edit);
  162. return edit;
  163. }
  164. private DateTimeEdit CreateTimeEdit(string header, int column, Action<TimeSpan> onChanged, bool leftMargin)
  165. {
  166. var label = new Label
  167. {
  168. Content = header,
  169. Margin = new Thickness(leftMargin ? 5 : 0, 0, 0, 0)
  170. };
  171. label.SetValue(Grid.ColumnProperty, column);
  172. var edit = new DateTimeEdit
  173. {
  174. Pattern = DateTimePattern.CustomPattern,
  175. CustomPattern = "HH:mm", //DateTimeFormat.Custom,
  176. //FormatString = "HH:mm",
  177. VerticalAlignment = VerticalAlignment.Stretch,
  178. VerticalContentAlignment = VerticalAlignment.Center,
  179. HorizontalAlignment = HorizontalAlignment.Stretch,
  180. HorizontalContentAlignment = HorizontalAlignment.Center,
  181. //TimeInterval = new TimeSpan(0, 15, 0),
  182. //ShowButtonSpinner = false
  183. DropDownView = DropDownViews.Clock,
  184. IsButtonPopUpEnabled = false
  185. };
  186. edit.SetValue(Grid.ColumnProperty, column + 1);
  187. edit.PreviewKeyDown += (o, e) =>
  188. {
  189. var separator = edit.Text.IndexOf(":");
  190. if (e.Key == Key.OemPeriod)
  191. {
  192. edit.Select(separator + 1, 2);
  193. e.Handled = true;
  194. }
  195. else if (e.Key == Key.Back)
  196. {
  197. if (string.Equals(edit.SelectedText, "00"))
  198. edit.Select(0, separator);
  199. else
  200. edit.SelectedText = "00";
  201. e.Handled = true;
  202. }
  203. else if (e.Key == Key.Tab)
  204. {
  205. if (Keyboard.IsKeyDown(Key.LeftShift) || Keyboard.IsKeyDown(Key.LeftShift))
  206. {
  207. if (edit.SelectionStart > separator)
  208. {
  209. edit.Select(0, separator);
  210. e.Handled = true;
  211. }
  212. }
  213. else
  214. {
  215. if (edit.SelectionLength != edit.Text.Length && edit.SelectionStart < separator)
  216. {
  217. edit.Select(separator + 1, 2);
  218. e.Handled = true;
  219. }
  220. }
  221. }
  222. };
  223. var changed = false;
  224. edit.DateTimeChanged += (o, e) =>
  225. {
  226. changed = true;
  227. };
  228. edit.LostFocus += (o, e) =>
  229. {
  230. if (changed)
  231. {
  232. onChanged(GetValue(edit));
  233. }
  234. };
  235. var less = new Button
  236. {
  237. Content = "<",
  238. Width = 23,
  239. Margin = new Thickness(2, 0, 0, 0),
  240. Focusable = false
  241. };
  242. less.SetValue(Grid.ColumnProperty, column + 2);
  243. less.Click += (o, e) =>
  244. {
  245. edit.DateTime = edit.DateTime.HasValue && edit.DateTime.Value.TimeOfDay >= new TimeSpan(0, 15, 0)
  246. ? edit.DateTime.Value.Subtract(new TimeSpan(0, 15, 0))
  247. : edit.DateTime;
  248. onChanged(GetValue(edit));
  249. };
  250. var more = new Button
  251. {
  252. Content = ">",
  253. Width = 23,
  254. Margin = new Thickness(2, 0, 0, 0),
  255. Focusable = false
  256. };
  257. more.SetValue(Grid.ColumnProperty, column + 3);
  258. more.Click += (o, e) =>
  259. {
  260. edit.DateTime = edit.DateTime.HasValue && edit.DateTime.Value.TimeOfDay < new TimeSpan(23, 45, 0)
  261. ? edit.DateTime.Value.Add(new TimeSpan(0, 15, 0))
  262. : edit.DateTime;
  263. onChanged(GetValue(edit));
  264. };
  265. Grid.Children.Add(label);
  266. Grid.Children.Add(edit);
  267. Grid.Children.Add(less);
  268. Grid.Children.Add(more);
  269. return edit;
  270. }
  271. private static TimeSpan GetValue(DateTimeEdit edit)
  272. {
  273. var result = new TimeSpan(0);
  274. if (edit.DateTime.HasValue)
  275. result = edit.DateTime.Value.TimeOfDay;
  276. result = new TimeSpan(result.Hours, result.Minutes, 0);
  277. return result;
  278. }
  279. private static void SetValue(DateTimeEdit edit, TimeSpan value)
  280. {
  281. if (value.Ticks > 0)
  282. edit.DateTime = DateTime.MinValue.Add(value);
  283. else
  284. edit.DateTime = null;
  285. }
  286. private static TimeSpan GetValue(TimeSpanEdit edit)
  287. {
  288. var result = new TimeSpan(0);
  289. if (edit.Value.HasValue)
  290. result = edit.Value.Value;
  291. return result;
  292. }
  293. private static void SetValue(TimeSpanEdit edit, TimeSpan value)
  294. {
  295. edit.Value = value;
  296. }
  297. public override int DesiredHeight()
  298. {
  299. return 25;
  300. }
  301. public override int DesiredWidth()
  302. {
  303. return int.MaxValue;
  304. }
  305. public override Dictionary<string, object?> GetValues()
  306. {
  307. return new Dictionary<string, object?>
  308. {
  309. { $"{ColumnName}.Start", Time.Start },
  310. { $"{ColumnName}.Duration", Time.Duration },
  311. { $"{ColumnName}.Finish", Time.Finish }
  312. };
  313. }
  314. public override object? GetValue(string property)
  315. {
  316. if (!property.StartsWith($"{ColumnName}.")) return null;
  317. property = property[(ColumnName.Length + 1)..];
  318. if (property == "Start") return Time.Start;
  319. if (property == "Duration") return Time.Duration;
  320. if (property == "Finish") return Time.Finish;
  321. return null;
  322. }
  323. public override void SetValue(string property, object? value)
  324. {
  325. if (!property.StartsWith($"{ColumnName}.")) return;
  326. property = property[(ColumnName.Length + 1)..];
  327. if (value is not TimeSpan timeSpan) return;
  328. if (property == "Start") Time.Start = timeSpan;
  329. else if (property == "Duration") Time.Duration = timeSpan;
  330. else if (property == "Finish") Time.Finish = timeSpan;
  331. UpdateEditors();
  332. }
  333. public override void SetColor(Color color)
  334. {
  335. Start.Background = new SolidColorBrush(color);
  336. Duration.Background = new SolidColorBrush(color);
  337. Finish.Background = new SolidColorBrush(color);
  338. }
  339. public override void SetFocus()
  340. {
  341. Start.Focus();
  342. }
  343. }
  344. }