Files
aistudio-wpf-diagram/Fluent.Ribbon/Fluent.Ribbon/Helpers/ToggleButtonHelper.cs
2021-07-23 09:42:22 +08:00

218 lines
7.1 KiB
C#

// ReSharper disable once CheckNamespace
namespace Fluent
{
using System;
using System.Collections;
using System.Reflection;
using System.Windows;
using System.Windows.Input;
using Fluent.Internal.KnownBoxes;
/// <summary>
/// Helper-Class for switching states in ToggleButton-Groups
/// </summary>
public static class ToggleButtonHelper
{
private static readonly MethodInfo getVisualRootMethodInfo = typeof(KeyboardNavigation).GetMethod("GetVisualRoot", BindingFlags.NonPublic | BindingFlags.Static);
// Grouped buttons
[ThreadStatic]
private static Hashtable groupNameToElements;
/// <summary>
/// Handles changes to <see cref="IToggleButton.GroupName" />
/// </summary>
public static void OnGroupNameChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
{
var toggleButton = (IToggleButton)d;
var newValue = e.NewValue as string;
var oldValue = e.OldValue as string;
if (newValue == oldValue)
{
return;
}
if (string.IsNullOrEmpty(oldValue) == false)
{
Unregister(oldValue, toggleButton);
}
if (string.IsNullOrEmpty(newValue))
{
return;
}
Register(newValue, toggleButton);
}
private static void Register(string groupName, IToggleButton toggleButton)
{
if (groupNameToElements is null)
{
groupNameToElements = new Hashtable(1);
}
var elements = (ArrayList)groupNameToElements[groupName];
if (elements is null)
{
elements = new ArrayList(1);
groupNameToElements[groupName] = elements;
}
else
{
PurgeDead(elements, null);
}
elements.Add(new WeakReference(toggleButton));
}
private static void Unregister(string groupName, IToggleButton toggleButton)
{
if (groupNameToElements is null)
{
return;
}
var groupNameToElement = (ArrayList)groupNameToElements[groupName];
if (groupNameToElement != null)
{
PurgeDead(groupNameToElement, toggleButton);
if (groupNameToElement.Count == 0)
{
groupNameToElements.Remove(groupName);
}
}
}
private static void PurgeDead(ArrayList elements, object elementToRemove)
{
var index = 0;
while (index < elements.Count)
{
var target = ((WeakReference)elements[index]).Target;
if (target is null
|| target == elementToRemove)
{
elements.RemoveAt(index);
}
else
{
++index;
}
}
}
/// <summary>
/// Updates the states of all buttons inside the group which <paramref name="toggleButton" /> belongs to.
/// </summary>
public static void UpdateButtonGroup(IToggleButton toggleButton)
{
var groupName = toggleButton.GroupName;
if (string.IsNullOrEmpty(groupName) == false)
{
var visualRoot = getVisualRootMethodInfo.Invoke(null, new object[] { (DependencyObject)toggleButton });
if (groupNameToElements is null)
{
groupNameToElements = new Hashtable(1);
}
var groupNameToElement = (ArrayList)groupNameToElements[groupName];
var index = 0;
while (index < groupNameToElement.Count)
{
var target = ((WeakReference)groupNameToElement[index]).Target as IToggleButton;
if (target is null)
{
groupNameToElement.RemoveAt(index);
}
else
{
if (target != toggleButton)
{
var isCheckedValue = GetIsCheckedValue(target);
if (isCheckedValue != 0
&& visualRoot == getVisualRootMethodInfo.Invoke(null, new object[] { (DependencyObject)target }))
{
UncheckToggleButton(target);
}
}
++index;
}
}
}
//else
//{
// var parent = toggleButton.Parent;
// if (parent is null)
// {
// return;
// }
// foreach (var child in LogicalTreeHelper.GetChildren(parent))
// {
// var childAsToggleButton = child as IToggleButton;
// if (childAsToggleButton != null
// && childAsToggleButton != toggleButton
// && string.IsNullOrEmpty(childAsToggleButton.GroupName))
// {
// var isCheckedValue = GetIsCheckedValue(childAsToggleButton);
// if (isCheckedValue != 0)
// {
// UncheckToggleButton(childAsToggleButton);
// }
// }
// }
//}
}
private static void UncheckToggleButton(IToggleButton toggleButton)
{
var dependencyObject = toggleButton as DependencyObject;
if (dependencyObject is null)
{
return;
}
if (toggleButton is System.Windows.Controls.MenuItem)
{
dependencyObject.SetCurrentValue(System.Windows.Controls.MenuItem.IsCheckedProperty, BooleanBoxes.FalseBox);
}
else
{
dependencyObject.SetCurrentValue(System.Windows.Controls.Primitives.ToggleButton.IsCheckedProperty, BooleanBoxes.FalseBox);
}
}
private static int GetIsCheckedValue(IToggleButton childAsToggleButton)
{
var isChecked = childAsToggleButton.IsChecked;
var isCheckedValue = isChecked.GetValueOrDefault()
? (isChecked.HasValue
? 1
: 0)
: 0;
return isCheckedValue;
}
/// <summary>
/// Handles changes to <see cref="IToggleButton.IsChecked" />
/// </summary>
public static void OnIsCheckedChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
{
if ((bool)e.NewValue)
{
UpdateButtonGroup((IToggleButton)d);
}
}
}
}