| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256 | using System;using System.Collections.Generic;using System.Drawing;using System.Globalization;using System.Windows;using System.Windows.Controls;using System.Windows.Media;using InABox.Core;using FontStyle = System.Windows.FontStyle;using Image = System.Windows.Controls.Image;namespace InABox.WPF{    public static class WPFUtils    {        public static T? FindLogicalParent<T>(this DependencyObject dependencyObject)            where T : DependencyObject        {            DependencyObject? parent = dependencyObject;             do            {                parent = LogicalTreeHelper.GetParent(parent);            } while(parent != null && parent is not T);            return parent as T;        }        public static int GetRow(this Grid grid, DependencyObject dependencyObject)        {            while (true)            {                var parent = LogicalTreeHelper.GetParent(dependencyObject);                if (parent == null)                    return -1;                if (parent == grid)                    return Grid.GetRow(dependencyObject as UIElement);                dependencyObject = parent;            }        }        public static int GetRowSpan(this Grid grid, DependencyObject dependencyObject)        {            while (true)            {                var parent = LogicalTreeHelper.GetParent(dependencyObject);                if (parent == null)                    return -1;                if (parent == grid)                    return Grid.GetRowSpan(dependencyObject as UIElement);                dependencyObject = parent;            }        }               public static int GetColumn(this Grid grid, DependencyObject dependencyObject)        {            while (true)            {                var parent = LogicalTreeHelper.GetParent(dependencyObject);                if (parent == null)                    return -1;                if (parent == grid)                    return Grid.GetColumn(dependencyObject as UIElement);                dependencyObject = parent;            }        }        public static int GetColumnSpan(this Grid grid, DependencyObject dependencyObject)        {            while (true)            {                var parent = LogicalTreeHelper.GetParent(dependencyObject);                if (parent == null)                    return -1;                if (parent == grid)                    return Grid.GetColumnSpan(dependencyObject as UIElement);                dependencyObject = parent;            }        }               public static void SetGridPosition(this FrameworkElement element, int row, int column, int rowspan = 1, int colspan = 1)        {            element.SetValue(Grid.ColumnProperty, column);            element.SetValue(Grid.ColumnSpanProperty, Math.Max(1, colspan));            element.SetValue(Grid.RowProperty, row);            element.SetValue(Grid.RowSpanProperty, Math.Max(1, rowspan));        }        public static IEnumerable<T> FindVisualChildren<T>(this DependencyObject depObj)        {            if (depObj != null)                //ContentControl cc = depObj as ContentControl;                //if (cc != null)                //{                //    if (cc.Content == null)                //        yield return null;                //    if (cc.Content is T)                //        yield return cc.Content as T;                //    foreach (var child in FindVisualChildren<T>(cc.Content as DependencyObject))                //        yield return child;                //}                //else                for (var i = 0; i < VisualTreeHelper.GetChildrenCount(depObj); i++)                {                    var child = VisualTreeHelper.GetChild(depObj, i);                    if (child is null)                        continue;                    if (child is T t)                        yield return t;                    foreach (var childOfChild in FindVisualChildren<T>(child))                        yield return childOfChild;                }        }        #region Menu Utils        private static void ItemsControlInsert(ItemsControl menu, FrameworkElement item, int index)        {            if (index != -1)            {                menu.Items.Insert(index, item);            }            else            {                menu.Items.Add(item);            }        }        private static MenuItem DoAddMenuItem(ItemsControl menu, string caption, Bitmap? image, bool enabled, int index = -1)        {            var item = new MenuItem { Header = caption, IsEnabled = enabled };            if (image != null)                item.Icon = new Image() { Source = enabled ? image.AsBitmapImage(24, 24) : image.AsGrayScale().AsBitmapImage(24, 24) };            ItemsControlInsert(menu, item, index);            return item;        }        private static MenuItem DoAddMenuItem(ItemsControl menu, string caption, Bitmap? image, Action? click, bool enabled, int index = -1)        {            var item = DoAddMenuItem(menu, caption, image, enabled, index);            if (click != null)            {                item.Click += (o, e) =>                {                    click();                };            }            return item;        }        private static MenuItem DoAddMenuItem<T>(ItemsControl menu, string caption, Bitmap? image, T tag, Action<T> click, bool enabled, int index = -1)        {            var item = DoAddMenuItem(menu, caption, image, enabled, index);            item.Tag = tag;            item.Click += (o, e) =>            {                click((T)(o as MenuItem)!.Tag);            };            return item;        }        public delegate void CheckToggleAction(bool isChecked);        public delegate void CheckToggleAction<T>(T tag, bool isChecked);        private static MenuItem DoAddCheckItem(ItemsControl menu, string caption, CheckToggleAction click, bool isChecked, bool enabled, int index = -1)        {            var item = new MenuItem { Header = caption, IsEnabled = enabled, IsCheckable = true, IsChecked = isChecked };            item.Click += (o, e) =>            {                click(item.IsChecked);            };            ItemsControlInsert(menu, item, index);            return item;        }        private static MenuItem DoAddCheckItem<T>(ItemsControl menu, string caption, T tag, CheckToggleAction<T> click, bool isChecked, bool enabled, int index = -1)        {            var item = new MenuItem { Header = caption, IsEnabled = enabled, IsCheckable = true, IsChecked = isChecked };            item.Tag = tag;            item.Click += (o, e) =>            {                click((T)(o as MenuItem)!.Tag, item.IsChecked);            };            ItemsControlInsert(menu, item, index);            return item;        }        private static Separator DoAddSeparator(ItemsControl menu, int index)        {            var separator = new Separator();            ItemsControlInsert(menu, separator, index);            return separator;        }        private static Separator? DoAddSeparatorIfNeeded(ItemsControl menu, int index)        {            if (menu.Items.Count == 0) return null;            var lastIndex = index != -1 ? index - 1 : menu.Items.Count - 1;            if (lastIndex < 0 || lastIndex >= menu.Items.Count) return null;            var last = menu.Items[lastIndex];            if (last is Separator) return null;            var separator = new Separator();            ItemsControlInsert(menu, separator, index);            return separator;        }        private static void DoRemoveUnnecessarySeparators(ItemsControl menu)        {            while(menu.Items.Count > 0 && menu.Items[0] is Separator)            {                menu.Items.RemoveAt(0);            }            while(menu.Items.Count > 0 && menu.Items[^1] is Separator)            {                menu.Items.RemoveAt(menu.Items.Count - 1);            }        }        public static Separator AddSeparator(this ContextMenu menu, int index = -1) => DoAddSeparator(menu, index);        public static Separator AddSeparator(this MenuItem menu, int index = -1) => DoAddSeparator(menu, index);        public static Separator? AddSeparatorIfNeeded(this ContextMenu menu, int index = -1) => DoAddSeparatorIfNeeded(menu, index);        public static Separator? AddSeparatorIfNeeded(this MenuItem menu, int index = -1) => DoAddSeparatorIfNeeded(menu, index);        public static void RemoveUnnecessarySeparators(this ContextMenu menu) => DoRemoveUnnecessarySeparators(menu);        public static void RemoveUnnecessarySeparators(this MenuItem menu) => DoRemoveUnnecessarySeparators(menu);        public static MenuItem AddItem(this ContextMenu menu, string caption, Bitmap? image, Action? click, bool enabled = true, int index = -1)            => DoAddMenuItem(menu, caption, image, click, enabled, index);        public static MenuItem AddItem(this MenuItem menu, string caption, Bitmap? image, Action? click, bool enabled = true, int index = -1)            => DoAddMenuItem(menu, caption, image, click, enabled, index);        public static MenuItem AddItem<T>(this ContextMenu menu, string caption, Bitmap? image, T tag, Action<T> click, bool enabled = true, int index = -1)            => DoAddMenuItem(menu, caption, image, tag, click, enabled, index);        public static MenuItem AddItem<T>(this MenuItem menu, string caption, Bitmap? image, T tag, Action<T> click, bool enabled = true, int index = -1)            => DoAddMenuItem(menu, caption, image, tag, click, enabled, index);        public static MenuItem AddCheckItem(this ContextMenu menu, string caption, CheckToggleAction click, bool isChecked = false, bool enabled = true, int index = -1)            => DoAddCheckItem(menu, caption, click, isChecked, enabled, index);        public static MenuItem AddCheckItem<T>(this ContextMenu menu, string caption, T tag, CheckToggleAction<T> click, bool isChecked = false, bool enabled = true, int index = -1)            => DoAddCheckItem(menu, caption, tag, click, isChecked, enabled, index);        #endregion    }}
 |