DFMultiSignatureControl.cs 8.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241
  1. using InABox.Core;
  2. using System.Collections.Generic;
  3. using System.Linq;
  4. using System.Text;
  5. using System.Threading.Tasks;
  6. using System.Windows.Controls;
  7. using System.Windows.Media.Effects;
  8. using System.Windows.Media.Imaging;
  9. using System.Windows.Media;
  10. using System.Windows;
  11. using InABox.WPF;
  12. using InABox.Wpf;
  13. namespace InABox.DynamicGrid
  14. {
  15. public class DFMultiSignatureControl : DynamicFormFieldControl<DFLayoutMultiSignaturePad, DFLayoutMultiSignaturePadProperties, Dictionary<string, byte[]>, Dictionary<string, byte[]>?>
  16. {
  17. private Grid Grid = null!; // Late-initialised
  18. private Grid Images = null!; // Late-initialised
  19. private bool Enabled = true;
  20. static DFMultiSignatureControl()
  21. {
  22. IsEnabledProperty.OverrideMetadata(
  23. typeof(DFMultiSignatureControl),
  24. new UIPropertyMetadata(
  25. true,
  26. ControlIsEnabledChanged));
  27. }
  28. private static void ControlIsEnabledChanged(DependencyObject obj, DependencyPropertyChangedEventArgs e)
  29. {
  30. var control = (DFMultiSignatureControl)obj;
  31. control.IsEnabled = true;
  32. control.Enabled = (bool)e.NewValue;
  33. }
  34. protected override FrameworkElement Create()
  35. {
  36. Grid = new Grid();
  37. Grid.ColumnDefinitions.Add(new ColumnDefinition { Width = GridLength.Auto });
  38. Grid.ColumnDefinitions.Add(new ColumnDefinition { Width = new GridLength(1, GridUnitType.Star) });
  39. Grid.ColumnDefinitions.Add(new ColumnDefinition { Width = GridLength.Auto });
  40. Grid.RowDefinitions.Add(new RowDefinition { Height = new GridLength(1, GridUnitType.Star) });
  41. Grid.RowDefinitions.Add(new RowDefinition { Height = GridLength.Auto });
  42. var imagesScroll = new ScrollViewer
  43. {
  44. HorizontalScrollBarVisibility = ScrollBarVisibility.Auto,
  45. VerticalScrollBarVisibility = ScrollBarVisibility.Disabled,
  46. Background = new SolidColorBrush(Colors.Gray)
  47. };
  48. Images = new Grid { Height = 150 };
  49. Images.RowDefinitions.Add(new RowDefinition { Height = new GridLength(1, GridUnitType.Star) });
  50. Images.RowDefinitions.Add(new RowDefinition { Height = GridLength.Auto });
  51. imagesScroll.Content = Images;
  52. var clearButton = new Button
  53. {
  54. Content = "Clear",
  55. Margin = new Thickness(0, 5, 0, 0),
  56. Width = 60,
  57. Height = 35
  58. };
  59. clearButton.Click += MultiSignatureClear_Click;
  60. var addButton = new Button
  61. {
  62. Content = "Add",
  63. Margin = new Thickness(0, 5, 0, 0),
  64. Width = 60,
  65. Height = 35
  66. };
  67. addButton.Click += MultiSignatureAdd_Click;
  68. imagesScroll.SetGridPosition(0, 0, 1, 3);
  69. clearButton.SetGridPosition(1, 0, 1, 1);
  70. addButton.SetGridPosition(1, 2, 1, 1);
  71. Grid.Children.Add(imagesScroll);
  72. Grid.Children.Add(clearButton);
  73. Grid.Children.Add(addButton);
  74. return Grid;
  75. }
  76. private void AddMultiSignature(BitmapSource? source, string name)
  77. {
  78. var image = new Image();
  79. if (source != null)
  80. {
  81. image.Source = source;
  82. var label = new Label
  83. {
  84. Content = name.ToUpper(),
  85. VerticalContentAlignment = VerticalAlignment.Center,
  86. VerticalAlignment = VerticalAlignment.Stretch,
  87. HorizontalContentAlignment = HorizontalAlignment.Center
  88. };
  89. var column = Images.ColumnDefinitions.Count;
  90. var menu = new ContextMenu();
  91. menu.AddItem("Remove Signature", null, image, MultiSignatureRemove_Click);
  92. image.ContextMenuOpening += (sender, args) =>
  93. {
  94. if (!Enabled) args.Handled = true;
  95. };
  96. Images.ColumnDefinitions.Add(new ColumnDefinition { Width = GridLength.Auto });
  97. image.ContextMenu = menu;
  98. label.ContextMenu = menu;
  99. image.SetGridPosition(0, column, 1, 1);
  100. label.SetGridPosition(1, column, 1, 1);
  101. Images.Children.Add(image);
  102. Images.Children.Add(label);
  103. }
  104. }
  105. private void MultiSignatureAdd_Click(object sender, RoutedEventArgs e)
  106. {
  107. var window = new SignaturePadWindow(null, true);
  108. window.ValidateName += sigName =>
  109. {
  110. sigName = sigName.ToUpper().Trim();
  111. if (string.IsNullOrWhiteSpace(sigName))
  112. {
  113. MessageWindow.ShowMessage("Name cannot be empty!", "Invalid Name");
  114. return false;
  115. }
  116. else if (Images.Children.Cast<UIElement>().Any(x => x is Label lbl && (string)lbl.Content == sigName))
  117. {
  118. MessageWindow.ShowMessage("A signature with that name already exists!", "Invalid Name");
  119. return false;
  120. }
  121. else
  122. {
  123. return true;
  124. }
  125. };
  126. if (window.ShowDialog() == true)
  127. {
  128. AddMultiSignature(window.Image, window.SignatureName);
  129. ChangeField();
  130. }
  131. }
  132. private void MultiSignatureRemove_Click(Image image)
  133. {
  134. var imageColumn = Grid.GetColumn(image);
  135. var removes = new List<UIElement>();
  136. foreach (var child in Images.Children)
  137. {
  138. if (child is UIElement el)
  139. {
  140. var column = Grid.GetColumn(el);
  141. if (column == imageColumn)
  142. removes.Add(el);
  143. else if (column > imageColumn)
  144. Grid.SetColumn(el, column - 1);
  145. }
  146. }
  147. foreach (var element in removes)
  148. {
  149. Images.Children.Remove(element);
  150. }
  151. ChangeField();
  152. }
  153. private void MultiSignatureClear_Click(object sender, RoutedEventArgs e)
  154. {
  155. if (Images.Children.Count > 0)
  156. {
  157. Images.Children.Clear();
  158. ChangeField();
  159. }
  160. }
  161. public override Dictionary<string, byte[]>? GetSerializedValue()
  162. {
  163. return GetValue();
  164. }
  165. public override void SetSerializedValue(Dictionary<string, byte[]>? value)
  166. {
  167. SetValue(value);
  168. }
  169. public override Dictionary<string, byte[]> GetValue()
  170. {
  171. var columns = Images.Children.Cast<UIElement>().GroupBy(x => Grid.GetColumn(x));
  172. var data = new Dictionary<string, byte[]>();
  173. foreach (var column in columns)
  174. {
  175. if (column.FirstOrDefault(x => x is Image) is Image image
  176. && column.FirstOrDefault(x => x is Label) is Label label)
  177. {
  178. var imgData = EmbeddedImageUtilities.SaveImageToBytes(image, false, new PngBitmapEncoder());
  179. if (imgData != null && label.Content is string str)
  180. {
  181. data.Add(str, imgData);
  182. }
  183. }
  184. }
  185. return data;
  186. }
  187. public override void SetValue(Dictionary<string, byte[]>? value)
  188. {
  189. Images.Children.Clear();
  190. if (value is IDictionary<string, byte[]> data)
  191. {
  192. foreach (var (name, imgData) in data)
  193. {
  194. AddMultiSignature(ImageUtils.BitmapImageFromBytes(imgData), name);
  195. }
  196. }
  197. }
  198. protected override void OnPropertyChanged(DependencyPropertyChangedEventArgs e)
  199. {
  200. base.OnPropertyChanged(e);
  201. if (e.Property == IsEnabledProperty)
  202. {
  203. Grid.RowDefinitions[1].Height = (bool)e.NewValue
  204. ? GridLength.Auto
  205. : new GridLength(0);
  206. }
  207. }
  208. protected override bool IsEmpty() => Images.Children.Count == 0;
  209. }
  210. }