using System.Drawing.Imaging; using VisionBuilder.UI.Common.ViewModel; namespace VisionBuilder.UI.Windows.Components { public partial class Stats : UserControl { private const string StartedAtLabel = "Started at"; private const string RecipeLabel = "Recipe"; private const string ProcessingTimeLabel = "Processing time"; private const string GoodLabel = "Good"; private const string BadLabel = "Bad"; private const string TotalLabel = "Total"; private const string DetailsLabel = "Details"; private const string ErrorRateLabel = "Error rate"; private const string FontFamilyName = "Verdana"; private const string Ellipsis = "..."; public void SetViewModel(StatisticsVM statisticsVm) { _statisticsVm = statisticsVm; _statisticsVm.PropertyChanged += _statisticsVm_PropertyChanged; Clear(); } private void _statisticsVm_PropertyChanged(object? sender, System.ComponentModel.PropertyChangedEventArgs e) { if (InvokeRequired) Invoke(() => HandleStatisticsPropertyChange(e.PropertyName!)); else HandleStatisticsPropertyChange(e.PropertyName!); } private void HandleStatisticsPropertyChange(string propertyName) { switch (propertyName) { case nameof(StatisticsVM.SessionStarted): Clear(); InitializeFields(); UpdateMeta(StartedAtLabel, _statisticsVm.SessionStarted, true); break; case nameof(StatisticsVM.RecipeName): // we don't use RecipeName(it's on button) //UpdateMeta(RecipeLabel, _statisticsVm.RecipeName, true); break; case nameof(StatisticsVM.ProcessingTime): UpdateMeta(ProcessingTimeLabel, _statisticsVm.ProcessingTime, true); break; case nameof(StatisticsVM.Good): // don't need to show good count //UpdateMeta(GoodLabel, _statisticsVm.Good.ToString(), false); break; case nameof(StatisticsVM.Bad): UpdateMeta(BadLabel, _statisticsVm.Bad.ToString(), false); break; case nameof(StatisticsVM.Total): UpdateMeta(TotalLabel, _statisticsVm.Total.ToString(), false); break; case nameof(StatisticsVM.StatisticsDetails): UpdateMeta(DetailsLabel, _statisticsVm.StatisticsDetails, false); break; case nameof(StatisticsVM.ErrorRate): UpdateMeta(ErrorRateLabel, _statisticsVm.ErrorRate, false); break; } } void InitializeFields() { UpdateMeta(StartedAtLabel,""); UpdateMeta(ProcessingTimeLabel, ""); UpdateMeta(TotalLabel, "0"); UpdateMeta(BadLabel, "0"); UpdateMeta(ErrorRateLabel, "0"); UpdateMeta(DetailsLabel, ""); } public Stats() { InitializeComponent(); _imageGoodIndicator = new Bitmap(32, 32, PixelFormat.Format32bppArgb); using (Graphics g = Graphics.FromImage(_imageGoodIndicator)) { g.Clear(Color.Transparent); g.FillEllipse(Brushes.Green, 0, 0, 32, 32); } _imageBadIndicator = new Bitmap(32, 32, PixelFormat.Format32bppArgb); using (Graphics g = Graphics.FromImage(_imageBadIndicator)) { g.Clear(Color.Transparent); g.FillEllipse(Brushes.Red, 0, 0, 32, 32); } } private Dictionary _meta = new Dictionary(); private readonly Bitmap _imageGoodIndicator; private readonly Bitmap _imageBadIndicator; private StatisticsVM _statisticsVm; public static string ShortenString(string input, int maxLength) { if (input.Length <= maxLength) { return input; } else { return input.Substring(0, maxLength) + Ellipsis; } } public void UpdateMeta(string name, string text, bool bold = false) { Action a = new Action(() => { if (!_meta.ContainsKey(name)) { metaPanel.Controls.Add(new Label() { AutoSize = true, Margin = new Padding(0, 8, 0, 0), Text = name + ":", Font = new Font(new FontFamily(FontFamilyName), 8, FontStyle.Bold) }); _meta[name] = new Label() { AutoSize = true, Margin = new Padding(0) }; _meta[name].Font = new Font(new FontFamily(FontFamilyName), 8, bold ? FontStyle.Bold : FontStyle.Regular); metaPanel.Controls.Add(_meta[name]); } _meta[name].Text = text; metaPanel.Refresh(); }); if (metaPanel.InvokeRequired) { metaPanel.Invoke(a); } else { a(); } } public void Clear() { _meta.Clear(); metaPanel.Controls.Clear(); InitializeFields(); } } }