From 93171994effa8a78330e1debab67917c9dd52d00 Mon Sep 17 00:00:00 2001 From: Aaron Date: Wed, 2 Oct 2024 09:13:35 +0100 Subject: [PATCH 1/2] Remove dependency on ReactiveUI This is no longer necessarily the default included with every new Avalonia project and would require you to install the correct version yourself to use the library. --- SukiUI/Controls/Hosts/SukiToastHost.cs | 29 ++-- .../PropertyGrid/PropertyGrid.axaml.cs | 9 +- SukiUI/Controls/SettingsLayout.axaml.cs | 48 +++--- SukiUI/Controls/Stepper.axaml.cs | 24 +-- SukiUI/Controls/SukiBackground.cs | 61 +++---- SukiUI/Controls/SukiSideMenu.axaml.cs | 80 ++++----- SukiUI/Controls/SukiSideMenuSearchService.cs | 6 +- .../SukiTransitioningContentControl.axaml.cs | 18 +- SukiUI/Controls/SukiWindow.axaml.cs | 159 +++++++++--------- SukiUI/SukiUI.csproj | 1 - SukiUI/Theme/Index.axaml.cs | 11 +- 11 files changed, 184 insertions(+), 262 deletions(-) diff --git a/SukiUI/Controls/Hosts/SukiToastHost.cs b/SukiUI/Controls/Hosts/SukiToastHost.cs index 05ccf6b3d..5ca71607e 100644 --- a/SukiUI/Controls/Hosts/SukiToastHost.cs +++ b/SukiUI/Controls/Hosts/SukiToastHost.cs @@ -1,7 +1,4 @@ using System; -using System.Linq; -using System.Reactive; -using System.Reactive.Linq; using System.Threading.Tasks; using Avalonia; using Avalonia.Controls; @@ -41,20 +38,22 @@ public ToastLocation Position set => SetValue(PositionProperty, value); } - private IDisposable? _subscriptions; - protected override void OnApplyTemplate(TemplateAppliedEventArgs e) { base.OnApplyTemplate(e); - _subscriptions = this.GetObservable(PositionProperty) - .Do(OnPositionChanged) - .Select(_ => Unit.Default).ObserveOn(new AvaloniaSynchronizationContext()) - .Subscribe(); + OnPositionChanged(Position); + } + + protected override void OnPropertyChanged(AvaloniaPropertyChangedEventArgs change) + { + base.OnPropertyChanged(change); + if (change.Property == PositionProperty && change.NewValue is ToastLocation loc) + OnPositionChanged(loc); } - private void OnPositionChanged(ToastLocation obj) + private void OnPositionChanged(ToastLocation newLoc) { - HorizontalAlignment = Position switch + HorizontalAlignment = newLoc switch { ToastLocation.BottomRight => HorizontalAlignment.Right, ToastLocation.BottomLeft => HorizontalAlignment.Left, @@ -62,7 +61,7 @@ private void OnPositionChanged(ToastLocation obj) ToastLocation.TopLeft => HorizontalAlignment.Left, _ => throw new ArgumentOutOfRangeException() }; - VerticalAlignment = Position switch + VerticalAlignment = newLoc switch { ToastLocation.BottomRight => VerticalAlignment.Bottom, ToastLocation.BottomLeft => VerticalAlignment.Bottom, @@ -71,12 +70,6 @@ private void OnPositionChanged(ToastLocation obj) _ => throw new ArgumentOutOfRangeException() }; } - - protected override void OnDetachedFromVisualTree(VisualTreeAttachmentEventArgs e) - { - base.OnDetachedFromVisualTree(e); - _subscriptions?.Dispose(); - } private static void OnManagerPropertyChanged(AvaloniaObject sender, AvaloniaPropertyChangedEventArgs propChanged) diff --git a/SukiUI/Controls/PropertyGrid/PropertyGrid.axaml.cs b/SukiUI/Controls/PropertyGrid/PropertyGrid.axaml.cs index f1dee40d9..30cf97184 100644 --- a/SukiUI/Controls/PropertyGrid/PropertyGrid.axaml.cs +++ b/SukiUI/Controls/PropertyGrid/PropertyGrid.axaml.cs @@ -2,17 +2,16 @@ using Avalonia.Controls; using Avalonia.Interactivity; using Avalonia.Markup.Xaml; -using System; using System.ComponentModel; -using System.Reactive.Linq; +// ReSharper disable once CheckNamespace namespace SukiUI.Controls { public partial class PropertyGrid : UserControl { static PropertyGrid() { - ItemProperty.Changed.Subscribe(OnItemChanged); + ItemProperty.Changed.AddClassHandler((_, args) => OnItemChanged(args)); } public PropertyGrid() @@ -40,8 +39,8 @@ public InstanceViewModel? Instance get { return GetValue(InstanceProperty); } set { SetValue(InstanceProperty, value); } } - - private static void OnItemChanged(AvaloniaPropertyChangedEventArgs e) + + private static void OnItemChanged( AvaloniaPropertyChangedEventArgs e) { if (e.Sender is PropertyGrid propertyGrid) { diff --git a/SukiUI/Controls/SettingsLayout.axaml.cs b/SukiUI/Controls/SettingsLayout.axaml.cs index b7b982c34..03e762914 100644 --- a/SukiUI/Controls/SettingsLayout.axaml.cs +++ b/SukiUI/Controls/SettingsLayout.axaml.cs @@ -8,14 +8,12 @@ using Avalonia.LogicalTree; using Avalonia.Markup.Xaml; using Avalonia.Styling; -using DynamicData; using System; using System.Collections.Generic; using System.Collections.ObjectModel; using System.Linq; using System.Threading; using System.Threading.Tasks; -using Avalonia.Layout; namespace SukiUI.Controls; @@ -32,11 +30,6 @@ public SettingsLayout() InitializeComponent(); } - protected override void OnAttachedToLogicalTree(LogicalTreeAttachmentEventArgs e) - { - base.OnAttachedToLogicalTree(e); - } - protected override void OnApplyTemplate(TemplateAppliedEventArgs e) { base.OnApplyTemplate(e); @@ -55,11 +48,10 @@ private void InitializeComponent() private ObservableCollection _items; public static readonly DirectProperty> StepsProperty = - AvaloniaProperty.RegisterDirect>(nameof(Items), l => l.Items, - (numpicker, v) => - { - numpicker.Items = v; - }, defaultBindingMode: BindingMode.TwoWay, enableDataValidation: true); + AvaloniaProperty.RegisterDirect>(nameof(Items), + l => l.Items, + (numpicker, v) => { numpicker.Items = v; }, defaultBindingMode: BindingMode.TwoWay, + enableDataValidation: true); public ObservableCollection Items { @@ -110,7 +102,7 @@ private void UpdateItems() var summaryButton = new RadioButton() { Content = new TextBlock() { Text = settingsLayoutItem.Header, FontSize = 17 }, - Classes = { new string[] { "MenuChip" } } + Classes = { "MenuChip" } }; summaryButton.Click += async (sender, args) => { @@ -119,7 +111,7 @@ private void UpdateItems() var x = border.TranslatePoint(new Point(), stackItems); if (x.HasValue) - await AnimateScroll(x.Value.Y); // myScroll.Offset = new Vector(0, x.Value.Y); + await AnimateScroll(x.Value.Y); // myScroll.Offset = new Vector(0, x.Value.Y); }; radios.Add(summaryButton); stackSummary.Children.Add(summaryButton); @@ -139,35 +131,28 @@ private void UpdateItems() }; } - private Mutex mut = new Mutex(); + private Mutex mut = new Mutex(); private double LastDesiredSize = -1; - + private async void DockPanel_SizeChanged(object sender, SizeChangedEventArgs e) { - var stack = this.GetTemplateChildren().First(n => n.Name == "StackSummary"); var desiredSize = e.NewSize.Width > 1100 ? 400 : 0; - - if(LastDesiredSize == desiredSize) + + if (LastDesiredSize == desiredSize) return; LastDesiredSize = desiredSize; - if (stack.Width != desiredSize && (stack.Width == 0 || stack.Width == 400)) + if (stack.Width != desiredSize && (stack.Width == 0 || stack.Width == 400)) stack.Animate(WidthProperty, stack.Width, desiredSize, TimeSpan.FromMilliseconds(800)); - - } private bool isAnimatingWidth = false; private bool isAnimatingMargin = false; private bool isAnimatingScroll = false; - - - - private async Task AnimateScroll(double desiredScroll) { isAnimatingScroll = true; @@ -189,7 +174,14 @@ private async Task AnimateScroll(double desiredScroll) }, new KeyFrame() { - Setters = { new Setter { Property = ScrollViewer.OffsetProperty, Value = new Vector(myscroll.Offset.X, desiredScroll -30) } }, + Setters = + { + new Setter + { + Property = ScrollViewer.OffsetProperty, + Value = new Vector(myscroll.Offset.X, desiredScroll - 30) + } + }, KeyTime = TimeSpan.FromMilliseconds(800) } } @@ -203,6 +195,4 @@ private async Task AnimateScroll(double desiredScroll) await Task.WhenAll(animationTask, abortTask); } - - } \ No newline at end of file diff --git a/SukiUI/Controls/Stepper.axaml.cs b/SukiUI/Controls/Stepper.axaml.cs index 836919c10..8b6471156 100644 --- a/SukiUI/Controls/Stepper.axaml.cs +++ b/SukiUI/Controls/Stepper.axaml.cs @@ -3,8 +3,6 @@ using System.Collections.Generic; using System.Collections.Specialized; using System.Linq; -using System.Reactive; -using System.Reactive.Linq; using Avalonia; using Avalonia.Controls; using Avalonia.Controls.Primitives; @@ -48,7 +46,6 @@ public IEnumerable? Steps } private Grid? _grid; - private IDisposable? _subscriptionDisposables; protected override void OnApplyTemplate(TemplateAppliedEventArgs e) { @@ -59,19 +56,14 @@ protected override void OnApplyTemplate(TemplateAppliedEventArgs e) } _grid = grid; + StepsChangedHandler(Steps); } - protected override void OnLoaded(RoutedEventArgs e) + protected override void OnPropertyChanged(AvaloniaPropertyChangedEventArgs change) { - var indexObs = this.GetObservable(IndexProperty) - .Do(_ => StepsChangedHandler(Steps)) - .Select(_ => Unit.Default); - _subscriptionDisposables = this.GetObservable(StepsProperty) - .Do(_ => StepsChangedHandler(Steps)) - .Select(_ => Unit.Default) - .Merge(indexObs) - .ObserveOn(new AvaloniaSynchronizationContext()) - .Subscribe(); + base.OnPropertyChanged(change); + if (change.Property == IndexProperty || change.Property == StepsProperty) + StepsChangedHandler(Steps); } private void StepsChangedHandler(IEnumerable? newSteps) @@ -217,12 +209,6 @@ private void AddStep(object step, int index, Grid grid, int stepCount) grid.Children.Add(griditem); } - protected override void OnUnloaded(RoutedEventArgs e) - { - base.OnUnloaded(e); - _subscriptionDisposables?.Dispose(); - } - #endregion #region StepperAlternateStyle diff --git a/SukiUI/Controls/SukiBackground.cs b/SukiUI/Controls/SukiBackground.cs index 107d4f0a3..e8bdaa681 100644 --- a/SukiUI/Controls/SukiBackground.cs +++ b/SukiUI/Controls/SukiBackground.cs @@ -1,13 +1,10 @@ using System; -using System.Reactive; -using System.Reactive.Linq; using Avalonia; using Avalonia.Controls; using Avalonia.Interactivity; using Avalonia.Media; using Avalonia.Threading; using SukiUI.Enums; -using SukiUI.Utilities; using SukiUI.Utilities.Effects; namespace SukiUI.Controls @@ -98,39 +95,36 @@ public bool ForceSoftwareRendering } private readonly EffectBackgroundDraw _draw; - private readonly IDisposable _observables; public SukiBackground() { IsHitTestVisible = false; _draw = new EffectBackgroundDraw(new Rect(0, 0, Bounds.Width, Bounds.Height)); - var forceSwRenderingObs = this.GetObservable(ForceSoftwareRenderingProperty) - .Do(enabled => _draw.ForceSoftwareRendering = enabled) - .Select(_ => Unit.Default); - var transEnabledObs = this.GetObservable(TransitionsEnabledProperty) - .Do(enabled => _draw.TransitionsEnabled = enabled) - .Select(_ => Unit.Default) - .Merge(forceSwRenderingObs); - var transTime = this.GetObservable(TransitionTimeProperty) - .Do(time => _draw.TransitionTime = time) - .Select(_ => Unit.Default) - .Merge(transEnabledObs); - var animObs = this.GetObservable(AnimationEnabledProperty) - .Do(enabled => _draw.AnimationEnabled = enabled) - .Select(_ => Unit.Default) - .Merge(transTime); - var bgStyleObs = this.GetObservable(StyleProperty) - .Select(_ => Unit.Default) - .Merge(animObs); - var bgShaderFileObs = this.GetObservable(ShaderFileProperty) - .Select(_ => Unit.Default) - .Merge(bgStyleObs); - var bgShaderCodeObs = this.GetObservable(ShaderCodeProperty) - .Select(_ => Unit.Default) - .Merge(bgShaderFileObs) - .Do(_ => HandleBackgroundStyleChanges()) - .ObserveOn(new AvaloniaSynchronizationContext()); - _observables = bgShaderCodeObs.Subscribe(); + } + + protected override void OnLoaded(RoutedEventArgs e) + { + base.OnLoaded(e); + _draw.ForceSoftwareRendering = ForceSoftwareRendering; + _draw.TransitionsEnabled = TransitionsEnabled; + _draw.TransitionTime = TransitionTime; + _draw.AnimationEnabled = AnimationEnabled; + HandleBackgroundStyleChanges(); + } + + protected override void OnPropertyChanged(AvaloniaPropertyChangedEventArgs change) + { + base.OnPropertyChanged(change); + if (change.Property == ForceSoftwareRenderingProperty && change.NewValue is bool forceSoftwareRendering) + _draw.ForceSoftwareRendering = forceSoftwareRendering; + else if(change.Property == TransitionsEnabledProperty && change.NewValue is bool transitionEnabled) + _draw.TransitionsEnabled = transitionEnabled; + else if(change.Property == TransitionTimeProperty && change.NewValue is double transitionTime) + _draw.TransitionTime = transitionTime; + else if(change.Property == AnimationEnabledProperty && change.NewValue is bool animationEnabled) + _draw.AnimationEnabled = animationEnabled; + else if(change.Property == StyleProperty || change.Property == ShaderFileProperty || change.Property == ShaderCodeProperty) + HandleBackgroundStyleChanges(); } public override void Render(DrawingContext context) @@ -149,10 +143,5 @@ private void HandleBackgroundStyleChanges() else _draw.Effect = SukiEffect.FromEmbeddedResource(Style.ToString()); } - - protected override void OnUnloaded(RoutedEventArgs e) - { - _observables.Dispose(); - } } } \ No newline at end of file diff --git a/SukiUI/Controls/SukiSideMenu.axaml.cs b/SukiUI/Controls/SukiSideMenu.axaml.cs index af0be225b..a90d085e8 100644 --- a/SukiUI/Controls/SukiSideMenu.axaml.cs +++ b/SukiUI/Controls/SukiSideMenu.axaml.cs @@ -1,12 +1,9 @@ using Avalonia; using Avalonia.Controls; using Avalonia.Controls.Primitives; -using Avalonia.Threading; using System; using System.Collections.Generic; using System.Linq; -using System.Reactive; -using System.Reactive.Linq; using Avalonia.Interactivity; using Avalonia.Layout; using SukiUI.Enums; @@ -112,15 +109,15 @@ public object? FooterContent private bool IsSpacerVisible => !IsMenuExpanded; - private IDisposable? _subscriptionDisposable; - private IDisposable? _contentDisposable; + + private SukiTransitioningContentControl? _contentControl; + private Grid? _spacer; public SukiSideMenu() { SelectionMode = SelectionMode.Single | SelectionMode.AlwaysSelected; } - private void MenuExpandedClicked() { IsMenuExpanded = !IsMenuExpanded; @@ -143,49 +140,43 @@ protected override void OnApplyTemplate(TemplateAppliedEventArgs e) SelectedItem = Items.First(); } - e.NameScope.Get