using System; using System.IO; using System.Linq; using System.Threading; using System.Threading.Tasks; using InABox.Core; using InABox.Mobile; using Syncfusion.XForms.SignaturePad; using Xamarin.Forms; namespace PRS.Mobile { public class DigitalFormSignature : MobileCard, IDigitalFormField { private readonly Grid _grid; private readonly SfSignaturePad _pad; private readonly Image _image; private readonly MobileButton _save; private readonly MobileButton _apply; private readonly MobileButton _clear; private DFLayoutSignaturePad _definition; public DFLayoutSignaturePad Definition { get => _definition; set { _definition = value; Initialize(value ?? new DFLayoutSignaturePad()); } } private Guid _id; private byte[] _value; public byte[] Value { get => _value; set { _value = value; UpdateValue(); } } public bool IsEmpty => Value?.Any() != true; private bool _readOnly; public bool ReadOnly { get => _readOnly; set { _readOnly = value; UpdateStatus(); } } public void Deserialize(string serialized) { if (String.IsNullOrWhiteSpace(serialized)) return; if (Guid.TryParse(serialized, out _id) && (_id != Guid.Empty)) DigitalFormDocumentFactory.LoadDocument(_id, v => Device.BeginInvokeOnMainThread(() => Value = v)); else if (serialized.IsBase64String()) Value = Convert.FromBase64String(serialized); } public string Serialize() { if ((_id == Guid.Empty) && Value?.Any() == true) _id = DigitalFormDocumentFactory.SaveDocument(Value); return _id.ToString(); } public event DigitalFormViewChangedHandler ValueChanged; public DigitalFormSignature() { Padding = 5; _grid = new Grid(); _grid.ColumnDefinitions.Add(new ColumnDefinition() { Width = GridLength.Star }); _grid.ColumnDefinitions.Add(new ColumnDefinition() { Width = GridLength.Star }); _grid.ColumnDefinitions.Add(new ColumnDefinition() { Width = GridLength.Star }); _grid.RowDefinitions.Add(new RowDefinition() { Height= GridLength.Star }); _grid.RowDefinitions.Add(new RowDefinition() { Height= GridLength.Auto }); _save = AddButton("Save New", SaveSignature, 0, false); _apply = AddButton("Apply Saved", ApplySignature, 1, App.Data.Me.Signature?.Any() == true); _clear = AddButton("Clear", ClearSignature, 2, false); _pad = new SfSignaturePad() { MinimumStrokeWidth = 0.2, MaximumStrokeWidth = 17, BackgroundColor = Color.Transparent }; _pad.StrokeCompleted += (sender, args) => { _save.IsEnabled = true; _clear.IsEnabled = true; }; _pad.SetValue(Grid.ColumnProperty,0); _pad.SetValue(Grid.ColumnSpanProperty,3); _pad.SetValue(Grid.RowProperty,0); _grid.Children.Add(_pad); _image = new Image { IsVisible = false }; _image.SetValue(Grid.ColumnProperty,0); _image.SetValue(Grid.ColumnSpanProperty,3); _image.SetValue(Grid.RowProperty,0); _grid.Children.Add(_image); Content = _grid; } private MobileButton AddButton(String text, Action clicked, int column, bool enabled) { var result = new MobileButton() { Text = text }; result.SetValue(Grid.RowProperty,1); result.SetValue(Grid.ColumnProperty,column); result.Clicked += (sender, args) => clicked(); result.IsEnabled = enabled; _grid.Children.Add(result); return result; } private void SaveSignature() { _pad.Save(); _value = GetSignature(_pad.ImageSource); App.Data.Me.Signature = _value; App.Data.Me.Save("Updated Signature"); _save.IsEnabled = false; _apply.IsEnabled = App.Data.Me.Signature?.Any() == true; UpdateValue(); } private void ApplySignature() { _value = App.Data.Me.Signature; _save.IsEnabled = false; UpdateValue(); } private void ClearSignature() { _pad.Clear(); _pad.Save(); _value = null; _save.IsEnabled = false; _clear.IsEnabled = false; UpdateValue(); } private byte[] GetSignature(ImageSource source) { try { StreamImageSource streamImageSource = (StreamImageSource)source; CancellationToken cancellationToken = CancellationToken.None; Task task = streamImageSource.Stream(cancellationToken); Stream stream = task.Result; byte[] bytes = new byte[stream.Length]; _ = stream.Read(bytes, 0, bytes.Length); return bytes; } catch (Exception e) { InABox.Mobile.MobileLogging.Log(e,"GetSignature"); return new byte[] { }; } } private void Initialize(DFLayoutSignaturePad definition) { UpdateStatus(); } private void UpdateStatus() { bool enabled = !_readOnly && !Definition.Properties.Secure; _pad.IsEnabled = enabled; _save.IsEnabled = enabled && (Value?.Any() == true); _apply.IsEnabled = enabled && (App.Data.Me.Signature?.Any() == true); _clear.IsEnabled = enabled && (Value?.Any() == true); var colors = DigitalFormUtils.GetColors(!enabled, Definition.Properties.Required, false); BackgroundColor = colors.Background; BorderColor = colors.Border; } private void UpdateValue() { if (_value == null) { _pad.Clear(); _pad.IsVisible = true; _image.IsVisible = false; } else { _pad.IsVisible = false; _image.Source = ImageSource.FromStream(() => new MemoryStream(_value)); _image.IsVisible = true; } UpdateStatus(); } } }