From 4be61880dd1e4cc5b21aa6b92d2c367cc13d0bbd Mon Sep 17 00:00:00 2001 From: Yusyuriv Date: Thu, 16 May 2024 22:57:10 +0600 Subject: [PATCH] Add CollapsedWhen and VisibleWhen markup extensions --- .../CollapsedWhenExtension.cs | 91 +++++++++++++++++++ .../HideableVisibilityConverter.cs | 48 ++++++++++ .../MarkupExtensions/VisibleWhenExtension.cs | 16 ++++ 3 files changed, 155 insertions(+) create mode 100644 Flow.Launcher/Resources/MarkupExtensions/CollapsedWhenExtension.cs create mode 100644 Flow.Launcher/Resources/MarkupExtensions/HideableVisibilityConverter.cs create mode 100644 Flow.Launcher/Resources/MarkupExtensions/VisibleWhenExtension.cs diff --git a/Flow.Launcher/Resources/MarkupExtensions/CollapsedWhenExtension.cs b/Flow.Launcher/Resources/MarkupExtensions/CollapsedWhenExtension.cs new file mode 100644 index 000000000..48022df48 --- /dev/null +++ b/Flow.Launcher/Resources/MarkupExtensions/CollapsedWhenExtension.cs @@ -0,0 +1,91 @@ +using System; +using System.Windows; +using System.Windows.Data; +using System.Windows.Markup; + +namespace Flow.Launcher.Resources.MarkupExtensions; + +#nullable enable + +public class CollapsedWhenExtension : MarkupExtension { + private Binding? When { get; set; } + public object? IsEqualTo { get; set; } + + public bool? IsEqualToBool + { + get => IsEqualTo switch + { + bool b => b, + _ => null + }; + set => IsEqualTo = value; + } + + public string? IsEqualToString + { + get => IsEqualTo switch + { + string s => s, + _ => null + }; + set => IsEqualTo = value; + } + + public int? IsEqualToInt + { + get => IsEqualTo switch + { + int i => i, + _ => null + }; + set => IsEqualTo = value; + } + protected virtual Visibility DefaultVisibility => Visibility.Visible; + protected virtual Visibility InvertedVisibility => Visibility.Collapsed; + + public CollapsedWhenExtension(Binding when) + { + When = when; + } + + public CollapsedWhenExtension(Binding when, object? isEqualTo) + { + When = when; + IsEqualTo = isEqualTo; + } + + public override object ProvideValue(IServiceProvider serviceProvider) { + if (serviceProvider.GetService(typeof(IProvideValueTarget)) is not IProvideValueTarget provideValueTarget) + return DependencyProperty.UnsetValue; + + if (provideValueTarget is not { TargetObject: not null, TargetProperty: not null }) + return DependencyProperty.UnsetValue; + + + if (When is null) + return DependencyProperty.UnsetValue; + + if (IsEqualTo is Binding isEqualToBinding) + { + var multiBinding = new MultiBinding + { + Converter = new HideableVisibilityConverter + { + DefaultVisibility = DefaultVisibility, + InvertedVisibility = InvertedVisibility + }, + Bindings = { When, isEqualToBinding } + }; + + return multiBinding.ProvideValue(serviceProvider); + } + + When.Converter = new HideableVisibilityConverter + { + DefaultVisibility = DefaultVisibility, + InvertedVisibility = InvertedVisibility, + IsEqualTo = IsEqualTo + }; + return When.ProvideValue(serviceProvider); + } +} diff --git a/Flow.Launcher/Resources/MarkupExtensions/HideableVisibilityConverter.cs b/Flow.Launcher/Resources/MarkupExtensions/HideableVisibilityConverter.cs new file mode 100644 index 000000000..877182e9b --- /dev/null +++ b/Flow.Launcher/Resources/MarkupExtensions/HideableVisibilityConverter.cs @@ -0,0 +1,48 @@ +using System; +using System.Diagnostics; +using System.Globalization; +using System.Windows; +using System.Windows.Data; + +namespace Flow.Launcher.Resources.MarkupExtensions; + +#nullable enable + +public class HideableVisibilityConverter : IMultiValueConverter, IValueConverter { + public Visibility DefaultVisibility { get; init; } = Visibility.Visible; + public Visibility InvertedVisibility { get; init; } = Visibility.Collapsed; + + public object? IsEqualTo { get; set; } + + public object Convert(object?[] values, Type targetType, object? parameter, CultureInfo culture) { + if (values is not { Length: 2 }) + return DependencyProperty.UnsetValue; + + var value1 = values[0]; + var value2 = values[1]; + if (value1 is Enum enum1 && value2 is Enum enum2) + { + value1 = System.Convert.ToInt32(enum1); + value2 = System.Convert.ToInt32(enum2); + } + + Debug.WriteLine($"HideableConverter: {value1} == {value2}"); + + return Equals(value1, value2) ? InvertedVisibility : DefaultVisibility; + } + + public object Convert(object? value, Type targetType, object? parameter, CultureInfo culture) + { + Debug.WriteLine($"HideableConverter: {value} ({value?.GetType()}) == {IsEqualTo} ({IsEqualTo?.GetType()})"); + return Equals(value, IsEqualTo) ? InvertedVisibility : DefaultVisibility; + } + + public object[] ConvertBack(object? value, Type[] targetTypes, object? parameter, CultureInfo culture) { + throw new NotSupportedException(); + } + + public object ConvertBack(object? value, Type targetType, object? parameter, CultureInfo culture) + { + throw new NotSupportedException(); + } +} diff --git a/Flow.Launcher/Resources/MarkupExtensions/VisibleWhenExtension.cs b/Flow.Launcher/Resources/MarkupExtensions/VisibleWhenExtension.cs new file mode 100644 index 000000000..ea322486c --- /dev/null +++ b/Flow.Launcher/Resources/MarkupExtensions/VisibleWhenExtension.cs @@ -0,0 +1,16 @@ +using System.Windows; +using System.Windows.Data; + +namespace Flow.Launcher.Resources.MarkupExtensions; + +#nullable enable + +public class VisibleWhenExtension : CollapsedWhenExtension +{ + protected override Visibility DefaultVisibility => Visibility.Collapsed; + protected override Visibility InvertedVisibility => Visibility.Visible; + + public VisibleWhenExtension(Binding when) : base(when) { } + + public VisibleWhenExtension(Binding when, object? isEqualTo) : base(when, isEqualTo) { } +}