using System; using System.Windows.Input; using Avalonia; using Avalonia.Controls; using Avalonia.Controls.Primitives; using Avalonia.Input; using Avalonia.Interactivity; using FAIconElement = FluentAvalonia.UI.Controls.FAIconElement; namespace FluentAvaloniaSamples.Controls; public class OptionsDisplayItem : TemplatedControl { public static readonly StyledProperty HeaderProperty = AvaloniaProperty.Register(nameof(Header)); public static readonly StyledProperty DescriptionProperty = AvaloniaProperty.Register(nameof(Description)); public static readonly StyledProperty IconProperty = AvaloniaProperty.Register(nameof(Icon)); public static readonly StyledProperty NavigatesProperty = AvaloniaProperty.Register(nameof(Navigates)); public static readonly StyledProperty ActionButtonProperty = AvaloniaProperty.Register(nameof(ActionButton)); public static readonly StyledProperty ExpandsProperty = AvaloniaProperty.Register(nameof(Expands)); public static readonly StyledProperty ContentProperty = ContentControl.ContentProperty.AddOwner(); public static readonly StyledProperty IsExpandedProperty = Expander.IsExpandedProperty.AddOwner(); public static readonly StyledProperty NavigationCommandProperty = AvaloniaProperty.Register(nameof(NavigationCommand)); public string Header { get => GetValue(HeaderProperty); set => SetValue(HeaderProperty, value); } public string Description { get => GetValue(DescriptionProperty); set => SetValue(DescriptionProperty, value); } public FAIconElement Icon { get => GetValue(IconProperty); set => SetValue(IconProperty, value); } public bool Navigates { get => GetValue(NavigatesProperty); set => SetValue(NavigatesProperty, value); } public Control ActionButton { get => GetValue(ActionButtonProperty); set => SetValue(ActionButtonProperty, value); } public bool Expands { get => GetValue(ExpandsProperty); set => SetValue(ExpandsProperty, value); } public object Content { get => GetValue(ContentProperty); set => SetValue(ContentProperty, value); } public bool IsExpanded { get => GetValue(IsExpandedProperty); set => SetValue(IsExpandedProperty, value); } public ICommand NavigationCommand { get => GetValue(NavigationCommandProperty); set => SetValue(NavigationCommandProperty, value); } public static readonly RoutedEvent NavigationRequestedEvent = RoutedEvent.Register(nameof(NavigationRequested), RoutingStrategies.Bubble); public event EventHandler NavigationRequested { add => AddHandler(NavigationRequestedEvent, value); remove => RemoveHandler(NavigationRequestedEvent, value); } protected override void OnPropertyChanged(AvaloniaPropertyChangedEventArgs change) { base.OnPropertyChanged(change); if (change.Property == NavigatesProperty) { if (Expands) throw new InvalidOperationException("Control cannot both Navigate and Expand"); PseudoClasses.Set(":navigates", change.GetNewValue()); } else if (change.Property == ExpandsProperty) { if (Navigates) throw new InvalidOperationException("Control cannot both Navigate and Expand"); PseudoClasses.Set(":expands", change.GetNewValue()); } else if (change.Property == IsExpandedProperty) { PseudoClasses.Set(":expanded", change.GetNewValue()); } else if (change.Property == IconProperty) { PseudoClasses.Set(":icon", change.NewValue != null); } } protected override void OnApplyTemplate(TemplateAppliedEventArgs e) { base.OnApplyTemplate(e); _layoutRoot = e.NameScope.Find("LayoutRoot"); _layoutRoot.PointerPressed += OnLayoutRootPointerPressed; _layoutRoot.PointerReleased += OnLayoutRootPointerReleased; _layoutRoot.PointerCaptureLost += OnLayoutRootPointerCaptureLost; } private void OnLayoutRootPointerPressed(object sender, PointerPressedEventArgs e) { if (e.GetCurrentPoint(this).Properties.PointerUpdateKind == PointerUpdateKind.LeftButtonPressed) { _isPressed = true; PseudoClasses.Set(":pressed", true); } } private void OnLayoutRootPointerReleased(object sender, PointerReleasedEventArgs e) { var pt = e.GetCurrentPoint(this); if (_isPressed && pt.Properties.PointerUpdateKind == PointerUpdateKind.LeftButtonReleased) { _isPressed = false; PseudoClasses.Set(":pressed", false); if (Expands) IsExpanded = !IsExpanded; if (Navigates) { RaiseEvent(new RoutedEventArgs(NavigationRequestedEvent, this)); NavigationCommand?.Execute(null); } } } private void OnLayoutRootPointerCaptureLost(object sender, PointerCaptureLostEventArgs e) { _isPressed = false; PseudoClasses.Set(":pressed", false); } private bool _isPressed; private bool _isExpanded; private Border _layoutRoot; }