2022-10-23 11:02:31 +13:00
|
|
|
|
// <copyright file="WPFExtensions.cs" company="PlaceholderCompany">
|
|
|
|
|
// Copyright (c) PlaceholderCompany. All rights reserved.
|
|
|
|
|
// </copyright>
|
|
|
|
|
//
|
|
|
|
|
// Copyright (c) 2022-2022 Peter Kirmeier
|
|
|
|
|
|
|
|
|
|
namespace SystemTrayMenu.Utilities
|
|
|
|
|
{
|
2022-11-30 10:48:45 +13:00
|
|
|
|
using System;
|
2022-11-14 07:58:54 +13:00
|
|
|
|
using System.Drawing;
|
|
|
|
|
using System.Globalization;
|
2022-10-23 11:02:31 +13:00
|
|
|
|
using System.Windows;
|
|
|
|
|
using System.Windows.Controls;
|
|
|
|
|
using System.Windows.Media;
|
2022-12-03 14:14:15 +13:00
|
|
|
|
using System.Windows.Threading;
|
2022-11-14 07:58:54 +13:00
|
|
|
|
using Point = System.Windows.Point;
|
2022-10-23 11:02:31 +13:00
|
|
|
|
|
|
|
|
|
internal static class WPFExtensions
|
|
|
|
|
{
|
2022-12-03 14:14:15 +13:00
|
|
|
|
internal static void HandleInvoke(this DispatcherObject instance, Action action)
|
|
|
|
|
{
|
|
|
|
|
if (instance!.CheckAccess())
|
|
|
|
|
{
|
|
|
|
|
action();
|
|
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
{
|
|
|
|
|
instance.Dispatcher.Invoke(action);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2022-10-23 11:02:31 +13:00
|
|
|
|
internal static Window GetParentWindow(this ListView listView)
|
|
|
|
|
{
|
|
|
|
|
var parent = VisualTreeHelper.GetParent(listView);
|
|
|
|
|
|
|
|
|
|
while (!(parent is Window))
|
|
|
|
|
{
|
|
|
|
|
parent = VisualTreeHelper.GetParent(parent);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return (Window)parent;
|
|
|
|
|
}
|
|
|
|
|
|
2022-11-30 10:48:45 +13:00
|
|
|
|
internal static int IndexOfSenderItem(this ListView listView, ListViewItem sender)
|
|
|
|
|
{
|
|
|
|
|
int index = listView.Items.IndexOf(sender.Content);
|
|
|
|
|
if (index < 0)
|
|
|
|
|
{
|
|
|
|
|
// Most likely the sender object is a "DiconnectedItem"
|
|
|
|
|
// Needs to be confirmed:
|
|
|
|
|
// May happen when focus gets lost while event is handled
|
|
|
|
|
// As this has not occurred on files but on folders
|
|
|
|
|
// that spawns a new menu window which will get focus
|
|
|
|
|
// it may be caused by the loss of focus.
|
|
|
|
|
// Workaround:
|
|
|
|
|
// If possible take index from selection
|
|
|
|
|
// we simply assume it is the first one.
|
|
|
|
|
// Otherwise fall back to index 0 which shall always work
|
|
|
|
|
// because there must be anything that has sent something.
|
|
|
|
|
index = Math.Min(listView.SelectedIndex, 0);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return index;
|
|
|
|
|
}
|
|
|
|
|
|
2022-10-23 11:02:31 +13:00
|
|
|
|
internal static T? FindVisualChildOfType<T>(this DependencyObject depObj, int index = 0)
|
|
|
|
|
where T : DependencyObject
|
|
|
|
|
{
|
|
|
|
|
for (int i = 0; i < VisualTreeHelper.GetChildrenCount(depObj); i++)
|
|
|
|
|
{
|
|
|
|
|
DependencyObject child = VisualTreeHelper.GetChild(depObj, i);
|
|
|
|
|
if (child != null)
|
|
|
|
|
{
|
|
|
|
|
if (child is T)
|
|
|
|
|
{
|
|
|
|
|
if (index-- == 0)
|
|
|
|
|
{
|
|
|
|
|
return (T)child;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
continue;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
T? childItem = child.FindVisualChildOfType<T>(index);
|
|
|
|
|
if (childItem != null)
|
|
|
|
|
{
|
|
|
|
|
return childItem;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return null;
|
|
|
|
|
}
|
|
|
|
|
|
2022-12-03 07:34:24 +13:00
|
|
|
|
internal static Point GetRelativeChildPositionTo(this Visual parent, Visual? child)
|
2022-10-23 11:02:31 +13:00
|
|
|
|
{
|
2022-12-03 07:34:24 +13:00
|
|
|
|
return child == null ? new() : child.TransformToAncestor(parent).Transform(new ());
|
2022-11-14 07:58:54 +13:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// TODO: Find and remove any unnecessary convertions
|
|
|
|
|
internal static ImageSource ToImageSource(this Icon icon)
|
|
|
|
|
{
|
|
|
|
|
return (ImageSource)new IconToImageSourceConverter().Convert(
|
|
|
|
|
icon,
|
|
|
|
|
typeof(ImageSource),
|
2022-12-03 14:14:15 +13:00
|
|
|
|
null!,
|
2022-11-14 07:58:54 +13:00
|
|
|
|
CultureInfo.InvariantCulture);
|
2022-10-23 11:02:31 +13:00
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|