Files
C4IT-F4SD-Client/FasdDesktopUi/Basics/Models/IFocusInvoker.cs
2025-11-11 11:03:42 +01:00

175 lines
5.9 KiB
C#

using FasdDesktopUi.Basics.Helper;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Reflection;
using System.Text;
using System.Threading.Tasks;
using System.Windows;
using System.Windows.Controls;
using static C4IT.Logging.cLogManager;
namespace FasdDesktopUi.Basics.Models
{
public interface IFocusInvoker
{
int? ParentIndex { get; }
UIElement ParentElement { get; }
}
public static class cFocusInvoker
{
public static EventHandler GotFocus = delegate { };
public static EventHandler LostFocus = delegate { };
private static void ReAllocate(this IFocusInvoker focusInvoker)
{
try
{
if (!(focusInvoker is FrameworkElement focusInvokerElement))
return;
if (focusInvoker.ParentElement is null)
return;
if (focusInvokerElement.Parent is Panel actualParentPanel)
actualParentPanel.Children.Remove(focusInvokerElement);
else if (focusInvokerElement.Parent is Decorator actualParentDecorator)
actualParentDecorator.Child = null;
else
return;
if (focusInvoker.ParentElement is Panel parentPanel)
{
if (focusInvoker.ParentIndex != null)
{
parentPanel.Children.RemoveAt(focusInvoker.ParentIndex.Value);
parentPanel.Children.Insert(focusInvoker.ParentIndex.Value, focusInvokerElement);
}
else
{
parentPanel.Children.Add(focusInvokerElement);
}
}
else if (focusInvoker.ParentElement is Decorator parentDecorator)
{
parentDecorator.Child = focusInvokerElement;
}
}
catch (Exception E)
{
LogException(E);
}
}
private static void ReAllocate(this FrameworkElement focusInvokerElement)
{
try
{
var preFocusParent = GetPreFocusParent(focusInvokerElement);
if (preFocusParent is null)
return;
if (focusInvokerElement.Parent is Panel actualParentPanel)
actualParentPanel.Children.Remove(focusInvokerElement);
else if (focusInvokerElement.Parent is Decorator actualParentDecorator)
actualParentDecorator.Child = null;
else
return;
if (preFocusParent is Panel parentPanel)
{
var preFocusChildIndex = GetPreFocusChildIndex(focusInvokerElement);
if (preFocusChildIndex != null)
{
parentPanel.Children.RemoveAt(preFocusChildIndex.Value);
parentPanel.Children.Insert(preFocusChildIndex.Value, focusInvokerElement);
}
else
{
parentPanel.Children.Add(focusInvokerElement);
}
}
else if (preFocusParent is Decorator parentDecorator)
{
parentDecorator.Child = focusInvokerElement;
}
}
catch (Exception E)
{
LogException(E);
}
}
public static void InvokeGotFocus(object sender, EventArgs e)
{
try
{
if (sender is FrameworkElement senderElement)
{
SetPreFocusParent(senderElement, senderElement.Parent);
if (senderElement.Parent is Panel actualParentPanel)
SetPreFocusChildIndex(senderElement, actualParentPanel.Children.IndexOf(senderElement));
}
GotFocus?.Invoke(sender, e);
}
catch (Exception E)
{
LogException(E);
}
}
public static void InvokeLostFocus(object sender, EventArgs e)
{
LostFocus?.Invoke(sender, e);
if (sender is IFocusInvoker focusSender)
focusSender.ReAllocate();
else if (sender is FrameworkElement senderElement)
senderElement.ReAllocate();
}
#region Attached Properties
#region PreFocusChildIndex
private static int? GetPreFocusChildIndex(DependencyObject obj)
{
return (int?)obj.GetValue(PreFocusChildIndexProperty);
}
private static void SetPreFocusChildIndex(DependencyObject obj, int? value)
{
obj.SetValue(PreFocusChildIndexProperty, value);
}
public static readonly DependencyProperty PreFocusChildIndexProperty =
DependencyProperty.RegisterAttached("PreFocusChildIndex", typeof(int?), typeof(UIElement), new PropertyMetadata(null));
#endregion
#region PreFocusParent
private static DependencyObject GetPreFocusParent(DependencyObject obj)
{
return (DependencyObject)obj.GetValue(PreFocusParentProperty);
}
private static void SetPreFocusParent(DependencyObject obj, DependencyObject value)
{
obj.SetValue(PreFocusParentProperty, value);
}
public static readonly DependencyProperty PreFocusParentProperty =
DependencyProperty.RegisterAttached("PreFocusParent", typeof(DependencyObject), typeof(UIElement), new PropertyMetadata(null));
#endregion
#endregion
}
}