1
0
mirror of https://github.com/Artemis-RGB/Artemis synced 2025-12-12 13:28:33 +00:00

UI - Move notifications to the overlay layer

This commit is contained in:
Robert 2023-07-31 22:20:25 +02:00
parent 02798b6d6e
commit 7eccdf079a
8 changed files with 84 additions and 35 deletions

View File

@ -0,0 +1,54 @@
using System;
using Avalonia;
using Avalonia.Controls;
using Avalonia.Controls.Primitives;
using Avalonia.Layout;
namespace Artemis.UI.Shared;
internal class NotificationHost : ContentControl
{
private IDisposable? _rootBoundsWatcher;
public NotificationHost()
{
Background = null;
HorizontalAlignment = HorizontalAlignment.Center;
VerticalAlignment = VerticalAlignment.Center;
}
protected override Type StyleKeyOverride => typeof(OverlayPopupHost);
protected override Size MeasureOverride(Size availableSize)
{
_ = base.MeasureOverride(availableSize);
if (VisualRoot is TopLevel tl)
return tl.ClientSize;
if (VisualRoot is Control c)
return c.Bounds.Size;
return default;
}
protected override void OnAttachedToVisualTree(VisualTreeAttachmentEventArgs e)
{
base.OnAttachedToVisualTree(e);
if (e.Root is Control wb)
// OverlayLayer is a Canvas, so we won't get a signal to resize if the window
// bounds change. Subscribe to force update
_rootBoundsWatcher = wb.GetObservable(BoundsProperty).Subscribe(_ => OnRootBoundsChanged());
}
protected override void OnDetachedFromVisualTree(VisualTreeAttachmentEventArgs e)
{
base.OnDetachedFromVisualTree(e);
_rootBoundsWatcher?.Dispose();
_rootBoundsWatcher = null;
}
private void OnRootBoundsChanged()
{
InvalidateMeasure();
}
}

View File

@ -2,11 +2,11 @@
using System.Threading.Tasks;
using System.Windows.Input;
using Avalonia.Controls;
using Avalonia.Controls.Primitives;
using Avalonia.Layout;
using Avalonia.Threading;
using FluentAvalonia.UI.Controls;
using ReactiveUI;
using Button = Avalonia.Controls.Button;
namespace Artemis.UI.Shared.Services.Builders;
@ -117,34 +117,34 @@ public class NotificationBuilder
/// <exception cref="ArtemisSharedUIException" />
public Action Show()
{
Panel? panel = _parent.Find<Panel>("NotificationContainer");
if (panel == null)
throw new ArtemisSharedUIException("Can't display a notification on a window without a NotificationContainer.");
Dispatcher.UIThread.Post(() =>
{
panel.Children.Add(_infoBar);
OverlayLayer? overlayLayer = OverlayLayer.GetOverlayLayer(_parent);
if (overlayLayer == null)
throw new ArtemisSharedUIException("Can't display a notification on a window an overlay layer.");
NotificationHost container = new() {Content = _infoBar};
overlayLayer.Children.Add(container);
_infoBar.Closed += InfoBarOnClosed;
_infoBar.IsOpen = true;
});
Task.Run(async () =>
{
await Task.Delay(_timeout);
Dispatcher.UIThread.Post(() => _infoBar.IsOpen = false);
Dispatcher.UIThread.InvokeAsync(async () =>
{
await Task.Delay(_timeout);
_infoBar.IsOpen = false;
});
return;
void InfoBarOnClosed(InfoBar sender, InfoBarClosedEventArgs args)
{
overlayLayer.Children.Remove(container);
_infoBar.Closed -= InfoBarOnClosed;
}
});
return () => Dispatcher.UIThread.Post(() => _infoBar.IsOpen = false);
}
private void InfoBarOnClosed(InfoBar sender, InfoBarClosedEventArgs args)
{
_infoBar.Closed -= InfoBarOnClosed;
if (_parent.Content is not Panel panel)
return;
panel.Children.Remove(_infoBar);
}
}
/// <summary>
@ -180,7 +180,7 @@ public class NotificationButtonBuilder
_action = action;
return this;
}
/// <summary>
/// Changes action that is called when the button is clicked.
/// </summary>
@ -222,9 +222,13 @@ public class NotificationButtonBuilder
button.Classes.Add("AppBarButton");
if (_action != null)
{
button.Command = ReactiveCommand.Create(() => _action());
}
else if (_asyncAction != null)
{
button.Command = ReactiveCommand.CreateFromTask(() => _asyncAction());
}
else if (_command != null)
{
button.Command = _command;

View File

@ -17,6 +17,8 @@
<Setter Property="Opacity" Value="0" />
<Setter Property="MaxWidth" Value="600" />
<Setter Property="Margin" Value="15"/>
<Setter Property="VerticalAlignment" Value="Bottom"/>
<Setter Property="HorizontalAlignment" Value="Right"/>
<Setter Property="Transitions">
<Transitions>
<DoubleTransition Property="Opacity" Duration="0:0:0.2"/>

View File

@ -1,17 +1,14 @@
<Styles xmlns="https://github.com/avaloniaui"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:controls="clr-namespace:FluentAvalonia.UI.Controls;assembly=FluentAvalonia">
xmlns:controls="clr-namespace:FluentAvalonia.UI.Controls;assembly=FluentAvalonia"
xmlns:shared="clr-namespace:Artemis.UI.Shared">
<Design.PreviewWith>
<Border Padding="20">
<!-- Add Controls for Previewer Here -->
</Border>
</Design.PreviewWith>
<Style Selector="StackPanel.notification-container">
<Setter Property="Spacing" Value="-25" />
</Style>
<Style Selector="StackPanel.notification-container controls|InfoBar">
<Style Selector="shared|NotificationHost controls|InfoBar">
<Setter Property="MaxHeight" Value="0" />
<Style.Animations>
<Animation Duration="0:0:0.2" Easing="CubicEaseOut" FillMode="Forward">

View File

@ -36,6 +36,5 @@
</Border>
<ContentControl Content="{CompiledBinding}" />
</DockPanel>
<StackPanel Classes="notification-container" Name="NotificationContainer" VerticalAlignment="Bottom" HorizontalAlignment="Right"/>
</Panel>
</windowing:AppWindow>

View File

@ -2,7 +2,6 @@
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:controls="clr-namespace:FluentAvalonia.UI.Controls;assembly=FluentAvalonia"
xmlns:avalonia="clr-namespace:Material.Icons.Avalonia;assembly=Material.Icons.Avalonia"
xmlns:debugger="clr-namespace:Artemis.UI.Screens.Debugger"
xmlns:shared="clr-namespace:Artemis.UI.Shared;assembly=Artemis.UI.Shared"
@ -35,7 +34,5 @@
<Border Classes="router-container" Grid.Column="1">
<ContentControl Content="{CompiledBinding SelectedItem}" Margin="15"></ContentControl>
</Border>
<StackPanel Grid.Column="0" Grid.ColumnSpan="2" Classes="notification-container" Name="NotificationContainer" VerticalAlignment="Bottom" HorizontalAlignment="Right" />
</Grid>
</windowing:AppWindow>

View File

@ -69,7 +69,5 @@
</Panel>
</Border>
<StackPanel Grid.Column="0" Grid.ColumnSpan="3" Classes="notification-container" Name="NotificationContainer" VerticalAlignment="Top" HorizontalAlignment="Right" />
</Grid>
</windowing:AppWindow>

View File

@ -70,7 +70,5 @@
<ContentControl Margin="0 0 5 0" Content="{CompiledBinding ConfigurationViewModel}"></ContentControl>
</ScrollViewer>
</Grid>
<StackPanel Name="NotificationContainer" Classes="notification-container" VerticalAlignment="Bottom" HorizontalAlignment="Right" />
</Panel>
</windowing:AppWindow>