DigitalFormSignature.cs 7.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233
  1. using System;
  2. using System.IO;
  3. using System.Linq;
  4. using System.Threading;
  5. using System.Threading.Tasks;
  6. using InABox.Core;
  7. using InABox.Mobile;
  8. using Syncfusion.XForms.SignaturePad;
  9. using Xamarin.Forms;
  10. namespace PRS.Mobile
  11. {
  12. public class DigitalFormSignature : MobileCard, IDigitalFormField<DFLayoutSignaturePad, DFLayoutSignaturePadProperties, byte[], byte[]?>
  13. {
  14. private readonly Grid _grid;
  15. private readonly SfSignaturePad _pad;
  16. private readonly Image _image;
  17. private readonly MobileButton _save;
  18. private readonly MobileButton _apply;
  19. private readonly MobileButton _clear;
  20. private DFLayoutSignaturePad _definition;
  21. public DFLayoutSignaturePad Definition
  22. {
  23. get => _definition;
  24. set
  25. {
  26. _definition = value;
  27. Initialize(value ?? new DFLayoutSignaturePad());
  28. }
  29. }
  30. private byte[] _value;
  31. public byte[] Value
  32. {
  33. get => _value;
  34. set
  35. {
  36. _value = value;
  37. UpdateValue();
  38. }
  39. }
  40. public void Deserialize(DFLoadStorageEntry entry)
  41. {
  42. Value = Definition?.Properties.DeserializeValue(entry) ?? new byte[] { };
  43. }
  44. public void Serialize(DFSaveStorageEntry entry)
  45. {
  46. if (_value?.Any() != true)
  47. {
  48. _pad.Save();
  49. _value = GetSignature(_pad.ImageSource);
  50. }
  51. Definition?.Properties.SerializeValue(entry,_value);
  52. }
  53. public bool IsEmpty => Value?.Any() != true;
  54. private bool _readOnly;
  55. public bool ReadOnly
  56. {
  57. get => _readOnly;
  58. set
  59. {
  60. _readOnly = value;
  61. UpdateStatus();
  62. }
  63. }
  64. public void Deserialize(string serialized)
  65. {
  66. if (!String.IsNullOrWhiteSpace(serialized) && serialized.IsBase64String())
  67. Value = Convert.FromBase64String(serialized);
  68. else
  69. Value = null;
  70. }
  71. public string Serialize()
  72. {
  73. if (_value?.Any() != true)
  74. {
  75. _pad.Save();
  76. _value = GetSignature(_pad.ImageSource);
  77. }
  78. return Convert.ToBase64String(_value ?? new byte[] { });
  79. }
  80. public event DigitalFormViewChangedHandler ValueChanged;
  81. public DigitalFormSignature()
  82. {
  83. Padding = 5;
  84. _grid = new Grid();
  85. _grid.ColumnDefinitions.Add(new ColumnDefinition() { Width = GridLength.Star });
  86. _grid.ColumnDefinitions.Add(new ColumnDefinition() { Width = GridLength.Star });
  87. _grid.ColumnDefinitions.Add(new ColumnDefinition() { Width = GridLength.Star });
  88. _grid.RowDefinitions.Add(new RowDefinition() { Height= GridLength.Star });
  89. _grid.RowDefinitions.Add(new RowDefinition() { Height= GridLength.Auto });
  90. _save = AddButton("Save New", SaveSignature, 0, false);
  91. _apply = AddButton("Apply Saved", ApplySignature, 1, App.Data.Me.Signature?.Any() == true);
  92. _clear = AddButton("Clear", ClearSignature, 2, false);
  93. _pad = new SfSignaturePad()
  94. {
  95. MinimumStrokeWidth = 0.2,
  96. MaximumStrokeWidth = 17,
  97. BackgroundColor = Color.Transparent
  98. };
  99. _pad.StrokeCompleted += (sender, args) =>
  100. {
  101. _save.IsEnabled = true;
  102. _clear.IsEnabled = true;
  103. };
  104. _pad.SetValue(Grid.ColumnProperty,0);
  105. _pad.SetValue(Grid.ColumnSpanProperty,3);
  106. _pad.SetValue(Grid.RowProperty,0);
  107. _grid.Children.Add(_pad);
  108. _image = new Image
  109. {
  110. IsVisible = false
  111. };
  112. _image.SetValue(Grid.ColumnProperty,0);
  113. _image.SetValue(Grid.ColumnSpanProperty,3);
  114. _image.SetValue(Grid.RowProperty,0);
  115. _grid.Children.Add(_image);
  116. Content = _grid;
  117. }
  118. private MobileButton AddButton(String text, Action clicked, int column, bool enabled)
  119. {
  120. var result = new MobileButton() { Text = text, CornerRadius = 5};
  121. result.SetValue(Grid.RowProperty,1);
  122. result.SetValue(Grid.ColumnProperty,column);
  123. result.Clicked += (sender, args) => clicked();
  124. result.IsEnabled = enabled;
  125. _grid.Children.Add(result);
  126. return result;
  127. }
  128. private void SaveSignature()
  129. {
  130. _pad.Save();
  131. _value = GetSignature(_pad.ImageSource);
  132. App.Data.Me.Signature = _value;
  133. App.Data.Me.Save("Updated Signature");
  134. _save.IsEnabled = false;
  135. _apply.IsEnabled = App.Data.Me.Signature?.Any() == true;
  136. UpdateValue();
  137. }
  138. private void ApplySignature()
  139. {
  140. _value = App.Data.Me.Signature;
  141. _save.IsEnabled = false;
  142. UpdateValue();
  143. }
  144. private void ClearSignature()
  145. {
  146. _pad.Clear();
  147. _pad.Save();
  148. _value = null;
  149. _save.IsEnabled = false;
  150. _clear.IsEnabled = false;
  151. UpdateValue();
  152. }
  153. private byte[] GetSignature(ImageSource source)
  154. {
  155. try
  156. {
  157. StreamImageSource streamImageSource = (StreamImageSource)source;
  158. CancellationToken cancellationToken = CancellationToken.None;
  159. Task<Stream> task = streamImageSource.Stream(cancellationToken);
  160. Stream stream = task.Result;
  161. byte[] bytes = new byte[stream.Length];
  162. _ = stream.Read(bytes, 0, bytes.Length);
  163. return bytes;
  164. }
  165. catch (Exception e)
  166. {
  167. InABox.Mobile.MobileLogging.Log(e,"GetSignature");
  168. return new byte[] { };
  169. }
  170. }
  171. private void Initialize(DFLayoutSignaturePad definition)
  172. {
  173. UpdateStatus();
  174. }
  175. private void UpdateStatus()
  176. {
  177. bool enabled = !_readOnly && !Definition.Properties.Secure;
  178. _pad.IsEnabled = enabled;
  179. _save.IsEnabled = enabled && (Value?.Any() == true);
  180. _apply.IsEnabled = enabled && (App.Data.Me.Signature?.Any() == true);
  181. _clear.IsEnabled = enabled && (Value?.Any() == true);
  182. var colors = DigitalFormUtils.GetColors(!enabled || _value?.Any() == true, Definition.Properties.Required, false);
  183. BackgroundColor = colors.Background;
  184. BorderColor = colors.Border;
  185. }
  186. private void UpdateValue()
  187. {
  188. if (_value?.Any() != true)
  189. {
  190. _pad.Clear();
  191. _pad.IsVisible = true;
  192. _image.IsVisible = false;
  193. }
  194. else
  195. {
  196. _pad.IsVisible = false;
  197. _image.Source = ImageSource.FromStream(() => new MemoryStream(_value));
  198. _image.IsVisible = true;
  199. }
  200. UpdateStatus();
  201. }
  202. }
  203. }