| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509 | using System;using System.Collections.Generic;using System.Linq;using System.Windows;using System.Windows.Controls;using System.Windows.Media;using InABox.Core;using Button = System.Windows.Controls.Button;using Color = System.Windows.Media.Color;using ComboBox = System.Windows.Controls.ComboBox;using HorizontalAlignment = System.Windows.HorizontalAlignment;using Label = System.Windows.Controls.Label;using SystemColors = System.Windows.SystemColors;using TextBox = System.Windows.Controls.TextBox;using UserControl = System.Windows.Controls.UserControl;namespace InABox.WPF{    public class QAGrid : UserControl    {        public delegate void QAFormChangedEvent(object sender, Dictionary<Guid, object> values);        private readonly Dictionary<QAQuestion, Border> borders = new();        private readonly Grid MasterGrid;        public QAGrid()        {            BorderBrush = new SolidColorBrush(Colors.Gray);            BorderThickness = new Thickness(0.75);            MasterGrid = new Grid();            MasterGrid.Background = new SolidColorBrush(Colors.WhiteSmoke);            MasterGrid.ColumnDefinitions.Add(new ColumnDefinition { Width = new GridLength(0.25F, GridUnitType.Star) });            MasterGrid.ColumnDefinitions.Add(new ColumnDefinition { Width = new GridLength(0.25F, GridUnitType.Star) });            MasterGrid.RowDefinitions.Add(new RowDefinition { Height = new GridLength(1.0F, GridUnitType.Auto) });            MasterGrid.RowDefinitions.Add(new RowDefinition { Height = new GridLength(1.0F, GridUnitType.Star) });            MasterGrid.RowDefinitions.Add(new RowDefinition { Height = new GridLength(1.0F, GridUnitType.Auto) });            Content = MasterGrid;        }        public bool Preview { get; set; }        public QAFormChangedEvent OnChanged { get; set; }        private object GetValue(Dictionary<Guid, object> values, Guid guid)        {            if (values.ContainsKey(guid))                return values[guid];            return "";        }        private Border CreateHeader(string title)        {            var label = new Label            {                Content = title,                FontSize = 16.0F,                HorizontalAlignment = HorizontalAlignment.Center,                VerticalAlignment = VerticalAlignment.Center            };            var border = new Border            {                CornerRadius = new CornerRadius(10.0F, 10.0F, 0.0F, 0.0F),                BorderThickness = new Thickness(1.0F),                BorderBrush = SystemColors.WindowFrameBrush,                Background = SystemColors.WindowBrush,                Margin = new Thickness(5.0F, 5.0F, 5.0F, 2.0F),                Padding = new Thickness(5.0F)            };            border.SetValue(Grid.ColumnProperty, MasterGrid.ColumnDefinitions.Count - 1);            border.SetValue(Grid.RowProperty, 0);            border.Child = label;            MasterGrid.Children.Add(border);            return border;        }        private Thickness GetMargin(Grid grid)        {            if (grid.RowDefinitions.Count == 0)                return new Thickness(2.0F, 0.0F, 2.0F, 0.0F);            return new Thickness(4.0F, 3.0F, 4.0F, 3.0F);        }        public static Color InterpolateColors(Color color1, Color color2, float percentage)        {            double a1 = color1.A / 255.0, r1 = color1.R / 255.0, g1 = color1.G / 255.0, b1 = color1.B / 255.0;            double a2 = color2.A / 255.0, r2 = color2.R / 255.0, g2 = color2.G / 255.0, b2 = color2.B / 255.0;            var a3 = Convert.ToByte((a1 + (a2 - a1) * percentage) * 255);            var r3 = Convert.ToByte((r1 + (r2 - r1) * percentage) * 255);            var g3 = Convert.ToByte((g1 + (g2 - g1) * percentage) * 255);            var b3 = Convert.ToByte((b1 + (b2 - b1) * percentage) * 255);            return Color.FromArgb(a3, r3, g3, b3);        }        private Color GetBorder(QAQuestion question, Dictionary<Guid, object> answers)        {            var parameters = question.ParseParameters();            var bAnswerRequired = question.Answer != QAAnswer.Comment &&                                  (!parameters.ContainsKey("Default") || string.IsNullOrWhiteSpace(parameters["Default"]));            if (bAnswerRequired && (!answers.ContainsKey(question.ID) || answers[question.ID] == null))                return Colors.Red;            return Colors.Transparent;        }        public void CollapseMargins()        {            MasterGrid.ColumnDefinitions.First().Width = new GridLength(0.0F);            MasterGrid.ColumnDefinitions.Last().Width = new GridLength(0.0F);        }        private void Changed(Dictionary<Guid, object> values)        {            OnChanged?.Invoke(this, values);            foreach (var question in borders.Keys)            {                var color = GetBorder(question, values);                borders[question].BorderBrush = new SolidColorBrush(color);                borders[question].Background = new SolidColorBrush(InterpolateColors(color, Colors.Transparent, 0.8F));            }        }        private Border CreateBorder(Grid grid, QAQuestion check, Dictionary<Guid, object> values)        {            var border = new Border();            border.SetValue(Grid.ColumnProperty, 0);            border.SetValue(Grid.RowProperty, grid.RowDefinitions.Count);            border.Padding = new Thickness(2.0F);            var color = GetBorder(check, values);            border.BorderBrush = new SolidColorBrush(color);            border.Background = new SolidColorBrush(InterpolateColors(color, Colors.Transparent, 0.8F));            border.BorderThickness = new Thickness(1.5F);            border.Margin = new Thickness(0F, 2F, 0F, 2F);            border.CornerRadius = new CornerRadius(5.0F);            grid.RowDefinitions.Add(new RowDefinition { Height = new GridLength(1.0F, GridUnitType.Auto) });            grid.Children.Add(border);            return border;        }        private Border CreateCommentPanel(Grid grid, QAQuestion check, Dictionary<Guid, object> values, int number)        {            var border = CreateBorder(grid, check, values);            var row = new Grid();            row.RowDefinitions.Add(new RowDefinition { Height = new GridLength(1.0F, GridUnitType.Star) });            row.ColumnDefinitions.Add(new ColumnDefinition { Width = new GridLength(1.0F, GridUnitType.Star) });            var label = new TextBlock            {                Text = check.Question,                FontSize = 14.0F,                TextAlignment = TextAlignment.Center,                TextWrapping = TextWrapping.Wrap,                VerticalAlignment = VerticalAlignment.Center,                Margin = GetMargin(grid),                Padding = new Thickness(10)            };            label.SetValue(Grid.RowProperty, 0);            label.SetValue(Grid.ColumnProperty, 0);            row.Children.Add(label);            border.Child = row;            return border;        }        private Border CreateChoicePanel(Grid grid, QAQuestion check, Dictionary<Guid, object> values, int number)        {            var border = CreateBorder(grid, check, values);            var row = new Grid();            row.RowDefinitions.Add(new RowDefinition { Height = new GridLength(1.0F, GridUnitType.Auto) });            row.ColumnDefinitions.Add(new ColumnDefinition { Width = new GridLength(1.0F, GridUnitType.Star) });            var label = new TextBlock            {                Text = string.Format("{0}. {1}", number, check.Question),                FontSize = 14.0F,                Margin = GetMargin(grid),                VerticalAlignment = VerticalAlignment.Center,                TextAlignment = TextAlignment.Left,                TextWrapping = TextWrapping.Wrap            };            label.SetValue(Grid.RowProperty, 0);            label.SetValue(Grid.ColumnProperty, 0);            row.Children.Add(label);            if (!string.IsNullOrEmpty(check.Parameters))            {                var parameters = check.ParseParameters();                var buttons = parameters["Options"].Split(',');                var colors = parameters["Colors"].Split(',');                var value = GetValue(values, check.ID).ToString();                if (string.IsNullOrWhiteSpace(value))                    value = parameters["Default"];                for (var i = 0; i < buttons.Length; i++)                    if (!string.IsNullOrWhiteSpace(buttons[i]))                    {                        var brush = new SolidColorBrush(Colors.WhiteSmoke);                        try                        {                            brush = new BrushConverter().ConvertFromString(colors[i]) as SolidColorBrush;                        }                        catch (Exception e)                        {                            Logger.Send(LogType.Error, "", string.Format("*** Unknown Error: {0}\n{1}", e.Message, e.StackTrace));                        }                        row.ColumnDefinitions.Add(new ColumnDefinition { Width = new GridLength(80.0F) });                        var button = new Button                        {                            Content = buttons[i],                            FontSize = 14.0F,                            Margin = GetMargin(grid),                            Height = 40,                            Background = buttons[i].Equals(value) ? brush : new SolidColorBrush(Colors.WhiteSmoke),                            Tag = brush                        };                        button.Click += (o, e) =>                        {                            values[check.ID] = button.Content.ToString();                            foreach (var other in row.Children)                                if (other is Button)                                {                                    if (other == button)                                        ((Button)other).Background = (SolidColorBrush)button.Tag;                                    else                                        ((Button)other).Background = new SolidColorBrush(Colors.WhiteSmoke);                                }                            Changed(values);                        };                        button.SetValue(Grid.RowProperty, 0);                        button.SetValue(Grid.ColumnProperty, i + 1);                        row.Children.Add(button);                    }            }            border.Child = row;            return border;        }        private Border CreateNumberPanel(Grid grid, QAQuestion check, Dictionary<Guid, object> values, int number)        {            var border = CreateBorder(grid, check, values);            var row = new Grid();            row.RowDefinitions.Add(new RowDefinition { Height = new GridLength(1.0F, GridUnitType.Star) });            row.ColumnDefinitions.Add(new ColumnDefinition { Width = new GridLength(1.0F, GridUnitType.Star) });            var label = new TextBlock            {                Text = string.Format("{0}. {1}", number, check.Question),                FontSize = 14.0F,                Margin = GetMargin(grid),                VerticalAlignment = VerticalAlignment.Center,                TextAlignment = TextAlignment.Left,                TextWrapping = TextWrapping.Wrap            };            label.SetValue(Grid.RowProperty, 0);            label.SetValue(Grid.ColumnProperty, 0);            row.Children.Add(label);            row.ColumnDefinitions.Add(new ColumnDefinition { Width = new GridLength(160.0F) });            var editor = new TextBox            {                Margin = GetMargin(grid),                TextAlignment = TextAlignment.Center,                VerticalContentAlignment = VerticalAlignment.Center,                Height = 40,                FontSize = 14.0F            };            editor.SetValue(Grid.RowProperty, 0);            editor.SetValue(Grid.ColumnProperty, 1);            row.Children.Add(editor);            var def = "";            if (!string.IsNullOrEmpty(check.Parameters))            {                var parameters = check.ParseParameters();                def = parameters["Default"];            }            var value = GetValue(values, check.ID).ToString();            editor.Text = string.IsNullOrWhiteSpace(value) ? def : value;            editor.TextChanged += (o, e) =>            {                values[check.ID] = editor.Text;                Changed(values);            };            border.Child = row;            return border;        }        private Border CreateTextPanel(Grid grid, QAQuestion check, Dictionary<Guid, object> values, int number)        {            var border = CreateBorder(grid, check, values);            var row = new Grid();            row.RowDefinitions.Add(new RowDefinition { Height = new GridLength(1.0F, GridUnitType.Star) });            row.ColumnDefinitions.Add(new ColumnDefinition { Width = new GridLength(1.0F, GridUnitType.Star) });            var label = new TextBlock            {                Text = string.Format("{0}. {1}", number, check.Question),                FontSize = 14.0F,                Margin = GetMargin(grid),                VerticalAlignment = VerticalAlignment.Center,                TextAlignment = TextAlignment.Left,                TextWrapping = TextWrapping.Wrap            };            label.SetValue(Grid.RowProperty, 0);            label.SetValue(Grid.ColumnProperty, 0);            row.Children.Add(label);            row.ColumnDefinitions.Add(new ColumnDefinition { Width = new GridLength(320.0F, GridUnitType.Pixel) });            var editor = new TextBox            {                Margin = GetMargin(grid),                TextAlignment = TextAlignment.Center,                VerticalContentAlignment = VerticalAlignment.Center,                Height = 40,                FontSize = 14.0F            };            editor.SetValue(Grid.RowProperty, 0);            editor.SetValue(Grid.ColumnProperty, 1);            row.Children.Add(editor);            var def = "";            if (!string.IsNullOrEmpty(check.Parameters))            {                var parameters = check.ParseParameters();                def = parameters["Default"];            }            var value = GetValue(values, check.ID).ToString();            editor.Text = string.IsNullOrWhiteSpace(value) ? def : value;            editor.TextChanged += (o, e) =>            {                values[check.ID] = editor.Text;                Changed(values);            };            border.Child = row;            return border;        }        private Border CreateComboPanel(Grid grid, QAQuestion check, Dictionary<Guid, object> values, int number)        {            var border = CreateBorder(grid, check, values);            var row = new Grid();            row.RowDefinitions.Add(new RowDefinition { Height = new GridLength(1.0F, GridUnitType.Star) });            row.ColumnDefinitions.Add(new ColumnDefinition { Width = new GridLength(1.0F, GridUnitType.Star) });            var label = new TextBlock            {                Text = string.Format("{0}. {1}", number, check.Question),                FontSize = 14.0F,                Margin = GetMargin(grid),                VerticalAlignment = VerticalAlignment.Center,                TextAlignment = TextAlignment.Left,                TextWrapping = TextWrapping.Wrap            };            label.SetValue(Grid.RowProperty, 0);            label.SetValue(Grid.ColumnProperty, 0);            row.Children.Add(label);            row.ColumnDefinitions.Add(new ColumnDefinition { Width = new GridLength(320.0F, GridUnitType.Pixel) });            var editor = new ComboBox            {                Margin = GetMargin(grid),                HorizontalContentAlignment = HorizontalAlignment.Left,                VerticalContentAlignment = VerticalAlignment.Center,                Height = 40            };            editor.SetValue(Grid.RowProperty, 0);            editor.SetValue(Grid.ColumnProperty, 1);            row.Children.Add(editor);            if (!string.IsNullOrEmpty(check.Parameters))            {                var parameters = check.ParseParameters();                var options = parameters["Options"].Split(',');                var def = parameters["Default"];                for (var i = 0; i < options.Length; i++)                    editor.Items.Add(options[i]);                var value = GetValue(values, check.ID).ToString();                editor.SelectedIndex = editor.Items.IndexOf(string.IsNullOrWhiteSpace(value) ? def : value);            }            editor.SelectionChanged += (o, e) =>            {                values[check.ID] = editor.SelectedIndex >= 0 ? editor.Items[editor.SelectedIndex].ToString() : "";                Changed(values);            };            border.Child = row;            return border;        }        public void Clear()        {            borders.Clear();            MasterGrid.Children.Clear();            MasterGrid.ColumnDefinitions.Clear();            MasterGrid.ColumnDefinitions.Add(new ColumnDefinition { Width = new GridLength(0.25F, GridUnitType.Star) });            MasterGrid.ColumnDefinitions.Add(new ColumnDefinition { Width = new GridLength(0.25F, GridUnitType.Star) });        }        public void LoadChecks(string title, IEnumerable<QAQuestion> checks, Dictionary<Guid, object> values)        {            var sections = new List<string>();            foreach (var check in checks)            {                var section = string.IsNullOrWhiteSpace(check.Section) ? title : check.Section;                if (!sections.Contains(section))                    sections.Add(section);            }            if (!sections.Any())                sections.Add(title);            foreach (var section in sections)            {                var header = CreateHeader(section);                var border = new Border                {                    CornerRadius = new CornerRadius(0.0F, 0.0F, 0.0F, 0.0F),                    BorderThickness = new Thickness(1.0F),                    BorderBrush = SystemColors.WindowFrameBrush,                    Background = SystemColors.WindowBrush,                    Margin = new Thickness(5.0F, 0.0F, 5.0F, 5.0F),                    Padding = new Thickness(10.0F, 10.0F, 5.0F, 10.0F)                };                border.SetValue(Grid.RowProperty, 1);                border.SetValue(Grid.ColumnProperty, MasterGrid.ColumnDefinitions.Count - 1);                if (MasterGrid.ColumnDefinitions.Count > 2)                {                    header.Margin = new Thickness(0.0F, 5.0F, 5.0F, 2.0F);                    border.Margin = new Thickness(0.0F, 0.0F, 5.0F, 5.0F);                    CollapseMargins();                }                MasterGrid.ColumnDefinitions.Insert(MasterGrid.ColumnDefinitions.Count - 1,                    new ColumnDefinition { Width = new GridLength(1F, GridUnitType.Star) });                MasterGrid.Children.Add(border);                var scroll = new ScrollViewer                {                    VerticalScrollBarVisibility = ScrollBarVisibility.Auto,                    HorizontalScrollBarVisibility = ScrollBarVisibility.Disabled,                    Padding = new Thickness(0.0F, 0.0F, 5.0F, 0.0F)                };                border.Child = scroll;                var grid = new Grid();                var i = 1;                if (!checks.Any())                {                    var check = new QAQuestion                    {                        Answer = QAAnswer.Comment,                        Question = "There are no checks defined for this form",                        Parameters = ""                    };                    borders[check] = CreateCommentPanel(grid, check, values, i);                }                else                {                    foreach (var check in checks)                    {                        Border element = null;                        if (check.Answer == QAAnswer.Comment)                            element = CreateCommentPanel(grid, check, values, i);                        else if (check.Answer == QAAnswer.Choice)                            element = CreateChoicePanel(grid, check, values, i++);                        else if (check.Answer == QAAnswer.Number)                            element = CreateNumberPanel(grid, check, values, i++);                        else if (check.Answer == QAAnswer.Text)                            element = CreateTextPanel(grid, check, values, i++);                        else if (check.Answer == QAAnswer.Combo)                            element = CreateComboPanel(grid, check, values, i++);                        if (element != null)                            borders[check] = element;                    }                }                scroll.Content = grid;            }        }    }}
 |