using System; using System.Collections.Generic; using System.Linq; using System.Threading.Tasks; using System.Windows.Media; using System.Windows; using System.Windows.Controls; using System.Diagnostics; using System.Windows.Controls.Primitives; using System.Text.RegularExpressions; using System.IO.Ports; using System.Net.Sockets; using System.Collections; namespace Elwig.Helpers { public static partial class Utils { public static int CurrentNextSeason => DateTime.Now.Year - (DateTime.Now.Month <= 3 ? 1 : 0); public static int CurrentLastSeason => DateTime.Now.Year - (DateTime.Now.Month <= 7 ? 1 : 0); public static DateTime Today => (DateTime.Now.Hour >= 3) ? DateTime.Today : DateTime.Today.AddDays(-1); public static readonly Regex SerialRegex = GeneratedSerialRegex(); public static readonly Regex TcpRegex = GeneratedTcpRegex(); [GeneratedRegex("^serial://([A-Za-z0-9]+):([0-9]+)(,([5-9]),([NOEMSnoems]),(0|1|1\\.5|2|))?$", RegexOptions.Compiled)] private static partial Regex GeneratedSerialRegex(); [GeneratedRegex("^tcp://[A-Za-z0-9:._-]+(:[0-9]+)?$", RegexOptions.Compiled)] private static partial Regex GeneratedTcpRegex(); public static SerialPort OpenSerialConnection(string connection) { var m = Utils.SerialRegex.Match(connection); if (!m.Success) throw new ArgumentException("Invalid connection string for scheme \"serial\""); var stop = m.Groups[6].Value; var parity = m.Groups[5].Value.ToUpper(); var data = m.Groups[4].Value; var port = new SerialPort() { PortName = m.Groups[1].Value, BaudRate = int.Parse(m.Groups[2].Value), Parity = parity == "E" ? Parity.Even : parity == "O" ? Parity.Odd : parity == "M" ? Parity.Mark : parity == "S" ? Parity.Space : Parity.None, DataBits = data == "" ? 8 : int.Parse(data), StopBits = (StopBits)(stop == "" ? 1 : stop == "1.5" ? 3 : stop[0] - '0'), Handshake = Handshake.None, }; port.Open(); return port; } public static TcpClient OpenTcpConnection(string connection) { var m = Utils.TcpRegex.Match(connection); if (!m.Success) throw new ArgumentException("Invalid connection string for scheme \"tcp\""); var client = new TcpClient() { SendTimeout = 250, ReceiveTimeout = 250, }; client.Connect(m.Groups[1].Value, int.Parse(m.Groups[2].Value)); return client; } private static void SetControlBrush(Control input, Brush brush) { if (input is ComboBox cb) { var border = GetComboBoxBorder(cb); if (border != null) border.BorderBrush = brush; } else if (input is Xceed.Wpf.Toolkit.CheckComboBox ccb) { var border = GetComboBoxBorder(ccb); if (border != null) border.BorderBrush = brush; } else { input.BorderBrush = brush; } } public static void SetInputChanged(Control input) { SetControlBrush(input, Brushes.Orange); } public static void SetInputInvalid(Control input) { SetControlBrush(input, Brushes.Red); } public static void ClearInputState(Control input) { if (input is ComboBox cb) { GetComboBoxBorder(cb)?.ClearValue(Border.BorderBrushProperty); } else if (input is Xceed.Wpf.Toolkit.CheckComboBox ccb) { GetComboBoxBorder(ccb)?.ClearValue(Border.BorderBrushProperty); } else { input.ClearValue(Control.BorderBrushProperty); } } private static Border? GetComboBoxBorder(ComboBox cb) { var toggleButton = cb.Template.FindName("toggleButton", cb) as ToggleButton; return toggleButton?.Template.FindName("templateRoot", toggleButton) as Border; } private static Border? GetComboBoxBorder(Xceed.Wpf.Toolkit.CheckComboBox ccb) { var toggleButton = ccb.Template.FindName("toggleButton", ccb) as ToggleButton; return toggleButton?.Template.FindName("templateRoot", toggleButton) as Border; } public static IEnumerable FindAllChildren(DependencyObject depObj) where T : DependencyObject { if (depObj == null) yield return (T)Enumerable.Empty(); foreach (var child in LogicalTreeHelper.GetChildren(depObj)) { if (child == null) { continue; } else if (child is T t) { yield return t; } else if (child is DependencyObject childDepOpj) { foreach (T childOfChild in FindAllChildren(childDepOpj)) { yield return childOfChild; } } } } public static IEnumerable FindAllChildren(DependencyObject depObj, IEnumerable exempt) where T : DependencyObject { return FindAllChildren(depObj).Where(c => !exempt.Contains(c)); } public static T? FindNextSibling(Control me) where T : DependencyObject { var found = false; foreach (var child in LogicalTreeHelper.GetChildren(me.Parent)) { if (found && child is T c) { return c; } else if (child == me) { found = true; } } return null; } public static void RenewItemsSource(Selector selector, IEnumerable? source, Func getId) { var selectedId = getId(selector.SelectedItem); selector.ItemsSource = source; if (selectedId != null && source != null) selector.SelectedItem = source.Cast().FirstOrDefault(i => selectedId.Equals(getId(i))); } public static void RenewItemsSource(Xceed.Wpf.Toolkit.Primitives.Selector selector, IEnumerable? source, Func getId) { var selectedIds = selector.SelectedItems.Cast().Select(i => getId(i)).ToList(); selector.ItemsSource = source; if (source != null) { foreach (var i in source.Cast().Where(i => selectedIds.Contains(getId(i)))) selector.SelectedItems.Add(i); } } public static void RenewItemsSource(DataGrid dataGrid, IEnumerable? source, Func getId, bool keepSort = true) { var column = dataGrid.CurrentCell.Column; var sortColumns = dataGrid.Columns.Select(c => c.SortDirection).ToList(); var sort = dataGrid.Items.SortDescriptions.ToList(); var selectedId = getId(dataGrid.SelectedItem); dataGrid.ItemsSource = source; if (keepSort) { for (int i = 0; i < dataGrid.Columns.Count; i++) dataGrid.Columns[i].SortDirection = sortColumns[i]; foreach (var s in sort) dataGrid.Items.SortDescriptions.Add(s); } if (selectedId != null && source != null) dataGrid.SelectedItem = source.Cast().FirstOrDefault(i => selectedId.Equals(getId(i))); if (dataGrid.SelectedItem != null && column != null) dataGrid.CurrentCell = new(dataGrid.SelectedItem, column); } public static void RenewItemsSource(ListBox listBox, IEnumerable? source, Func getId) { var selectedId = getId(listBox.SelectedItem); listBox.ItemsSource = source; if (selectedId != null && source != null) listBox.SelectedItem = source.Cast().FirstOrDefault(i => selectedId.Equals(getId(i))); } public static int Modulo(string a, int b) { if (a.Length == 0 || !a.All(char.IsAsciiDigit)) { throw new ArgumentException("First argument has to be a decimal string"); } else if (b < 2) { throw new ArgumentException("Second argument has to be greater than 1"); } return a.Select(ch => ch - '0').Aggregate((sum, n) => (sum * 10 + n) % b); } public static void RunBackground(string title, Func a) { Task.Run(async () => { try { await a(); } catch (Exception e) { MessageBox.Show(e.ToString(), title, MessageBoxButton.OK, MessageBoxImage.Error); } }); } public static void MailTo(string emailAddress) { Process.Start(new ProcessStartInfo() { FileName = $"mailto:{emailAddress}", UseShellExecute = true, }); } public static double KmwToOe(double kmw) { return Math.Round(kmw * (4.54 + 0.022 * kmw), 0); } public static double OeToKmw(double oe) { return Math.Round((-4.54 + Math.Sqrt(4.54 * 4.54 - 4 * 0.022 * -oe)) / (2 * 0.022), 1); } public static decimal DecFromDb(long value, byte precision) { bool neg = value < 0; if (neg) value = -value; return new((int)(value & 0xFFFFFFFF), (int)((value >> 32) & 0x7FFFFFFF), 0, neg, precision); } public static long DecToDb(decimal value, byte precision) { return (long)decimal.Round(value * (decimal)Math.Pow(10, precision), 0); } public static int GetAge(DateOnly birthday) { var today = DateTime.Today; var a = (today.Year * 100 + today.Month) * 100 + today.Day; var b = (birthday.Year * 100 + birthday.Month) * 100 + birthday.Day; return (a - b) / 10000; } public static int GetSearchScore(IEnumerable words, IEnumerable searchKeywords) { searchKeywords = searchKeywords.Where(s => s.Length >= 2 || (s.Length > 0 && s.All(c => char.IsAsciiDigit(c)))); if (!searchKeywords.Any()) return 0; words = words.Select(w => w?.ToLower()); int i = 0; foreach (string? c in words) { if (c == null) continue; var parts = c.Split(" "); if (searchKeywords.Any(f => c == f)) { i += 100; } else if (searchKeywords.Any(f => parts.Any(a => a == f))) { i += 90; } else if (searchKeywords.Any(f => parts.Any(a => a.StartsWith(f)))) { i += 50; } else if (searchKeywords.Any(f => f != null && c.Contains(f))) { i += 1; } } return i; } public static object? GetItemFromSource(IEnumerable source, Func getId, object? id) { if (source == null) return null; var items = source.Cast(); var item = items.Where(i => getId(i)?.Equals(id) ?? false).FirstOrDefault(); if (item == null && items.Any(i => i is NullItem)) return items.Where(i => i is NullItem).First(); return item; } public static object? GetItemFromSource(IEnumerable source, object? item, Func getId) { return GetItemFromSource(source, getId, getId(item)); } public static void SelectComboBoxItem(ComboBox cb, Func getId, object? id) { cb.SelectedItem = GetItemFromSource(cb.ItemsSource, getId, id); } public static void SelectComboBoxItem(ComboBox cb, object? item, Func getId) { SelectComboBoxItem(cb, getId, getId(item)); } public static IEnumerable GetItemsFromSource(IEnumerable source, Func getId, IEnumerable ids) { if (source == null) return Array.Empty(); return source.Cast().Where(i => ids.Any(c => c?.Equals(getId(i)) ?? false)); } public static IEnumerable GetItemsFromSource(IEnumerable source, IEnumerable? items, Func getId) { if (items == null) return Array.Empty(); return GetItemsFromSource(source, getId, items.Select(i => getId(i))); } public static void SelectCheckComboBoxItems(Xceed.Wpf.Toolkit.CheckComboBox ccb, Func getId, IEnumerable? ids) { ccb.SelectedItems.Clear(); if (ids == null) return; foreach (var id in ids) ccb.SelectedItems.Add(GetItemFromSource(ccb.ItemsSource, getId, id)); } public static void SelectCheckComboBoxItems(Xceed.Wpf.Toolkit.CheckComboBox ccb, IEnumerable? items, Func getId) { SelectCheckComboBoxItems(ccb, getId, items?.Select(i => getId(i))); } } }