using InABox.Core; using System.Collections.Generic; using System.Linq; using System.Text; using System.Threading.Tasks; using System.Windows.Controls; using System.Windows.Media.Effects; using System.Windows.Media.Imaging; using System.Windows.Media; using System.Windows; using InABox.WPF; namespace InABox.DynamicGrid { public class DFMultiSignatureControl : DynamicFormFieldControl, Dictionary?> { private Grid Grid = null!; // Late-initialised private Grid Images = null!; // Late-initialised private bool Enabled = true; static DFMultiSignatureControl() { IsEnabledProperty.OverrideMetadata( typeof(DFMultiSignatureControl), new UIPropertyMetadata( true, ControlIsEnabledChanged)); } private static void ControlIsEnabledChanged(DependencyObject obj, DependencyPropertyChangedEventArgs e) { var control = (DFMultiSignatureControl)obj; control.IsEnabled = true; control.Enabled = (bool)e.NewValue; } protected override FrameworkElement Create() { Grid = new Grid(); Grid.ColumnDefinitions.Add(new ColumnDefinition { Width = GridLength.Auto }); Grid.ColumnDefinitions.Add(new ColumnDefinition { Width = new GridLength(1, GridUnitType.Star) }); Grid.ColumnDefinitions.Add(new ColumnDefinition { Width = GridLength.Auto }); Grid.RowDefinitions.Add(new RowDefinition { Height = new GridLength(1, GridUnitType.Star) }); Grid.RowDefinitions.Add(new RowDefinition { Height = GridLength.Auto }); var imagesScroll = new ScrollViewer { HorizontalScrollBarVisibility = ScrollBarVisibility.Auto, VerticalScrollBarVisibility = ScrollBarVisibility.Disabled, Background = new SolidColorBrush(Colors.Gray) }; Images = new Grid { Height = 150 }; Images.RowDefinitions.Add(new RowDefinition { Height = new GridLength(1, GridUnitType.Star) }); Images.RowDefinitions.Add(new RowDefinition { Height = GridLength.Auto }); imagesScroll.Content = Images; var clearButton = new Button { Content = "Clear", Margin = new Thickness(0, 5, 0, 0), Width = 60, Height = 35 }; clearButton.Click += MultiSignatureClear_Click; var addButton = new Button { Content = "Add", Margin = new Thickness(0, 5, 0, 0), Width = 60, Height = 35 }; addButton.Click += MultiSignatureAdd_Click; imagesScroll.SetGridPosition(0, 0, 1, 3); clearButton.SetGridPosition(1, 0, 1, 1); addButton.SetGridPosition(1, 2, 1, 1); Grid.Children.Add(imagesScroll); Grid.Children.Add(clearButton); Grid.Children.Add(addButton); return Grid; } private void AddMultiSignature(BitmapSource? source, string name) { var image = new Image(); if (source != null) { image.Source = source; var label = new Label { Content = name.ToUpper(), VerticalContentAlignment = VerticalAlignment.Center, VerticalAlignment = VerticalAlignment.Stretch, HorizontalContentAlignment = HorizontalAlignment.Center }; var column = Images.ColumnDefinitions.Count; var menu = new ContextMenu(); menu.AddItem("Remove Signature", null, image, MultiSignatureRemove_Click); image.ContextMenuOpening += (sender, args) => { if (!Enabled) args.Handled = true; }; Images.ColumnDefinitions.Add(new ColumnDefinition { Width = GridLength.Auto }); image.ContextMenu = menu; label.ContextMenu = menu; image.SetGridPosition(0, column, 1, 1); label.SetGridPosition(1, column, 1, 1); Images.Children.Add(image); Images.Children.Add(label); } } private void MultiSignatureAdd_Click(object sender, RoutedEventArgs e) { var window = new SignaturePadWindow(null, true); if (window.ShowDialog() == true) { var sigName = window.SignatureName.ToUpper().Trim(); if (string.IsNullOrWhiteSpace(sigName)) { MessageBox.Show("Name cannot be empty!"); } else if (Images.Children.Cast().Any(x => x is Label lbl && (string)lbl.Content == sigName)) { MessageBox.Show("A signature with that name already exists!"); } else { AddMultiSignature(window.Image, window.SignatureName); ChangeField(); } } } private void MultiSignatureRemove_Click(Image image) { var imageColumn = Grid.GetColumn(image); var removes = new List(); foreach (var child in Images.Children) { if (child is UIElement el) { var column = Grid.GetColumn(el); if (column == imageColumn) removes.Add(el); else if (column > imageColumn) Grid.SetColumn(el, column - 1); } } foreach (var element in removes) { Images.Children.Remove(element); } ChangeField(); } private void MultiSignatureClear_Click(object sender, RoutedEventArgs e) { if (Images.Children.Count > 0) { Images.Children.Clear(); ChangeField(); } } public override Dictionary? GetSerializedValue() { return GetValue(); } public override void SetSerializedValue(Dictionary? value) { SetValue(value); } public override Dictionary GetValue() { var columns = Images.Children.Cast().GroupBy(x => Grid.GetColumn(x)); var data = new Dictionary(); foreach (var column in columns) { if (column.FirstOrDefault(x => x is Image) is Image image && column.FirstOrDefault(x => x is Label) is Label label) { var imgData = EmbeddedImageUtilities.SaveImageToBytes(image, false, new PngBitmapEncoder()); if (imgData != null && label.Content is string str) { data.Add(str, imgData); } } } return data; } public override void SetValue(Dictionary? value) { Images.Children.Clear(); if (value is IDictionary data) { foreach (var (name, imgData) in data) { AddMultiSignature(ImageUtils.BitmapImageFromBytes(imgData), name); } } } protected override void OnPropertyChanged(DependencyPropertyChangedEventArgs e) { base.OnPropertyChanged(e); if (e.Property == IsEnabledProperty) { Grid.RowDefinitions[1].Height = (bool)e.NewValue ? GridLength.Auto : new GridLength(0); } } protected override bool IsEmpty() => Images.Children.Count == 0; } }