CoreTimeEditorControl.cs 13 KB

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