Browse Source

polish notifications

pull/2453/head
Dan Walmsley 7 years ago
parent
commit
f8f5610b8c
  1. 19
      samples/ControlCatalog/ViewModels/MainWindowViewModel.cs
  2. 15
      samples/ControlCatalog/ViewModels/NotificationViewModel.cs
  3. 8
      samples/ControlCatalog/Views/NotificationView.xaml
  4. 2
      src/Avalonia.Controls/Notifications/INotificationManager.cs
  5. 10
      src/Avalonia.Controls/Notifications/Notification.cs
  6. 9
      src/Avalonia.Controls/Notifications/NotificationArea.cs
  7. 6
      src/Avalonia.Controls/Notifications/NotificationContent.cs
  8. 8
      src/Avalonia.Controls/TopLevel.cs
  9. 51
      src/Avalonia.Themes.Default/NotificationArea.xaml

19
samples/ControlCatalog/ViewModels/MainWindowViewModel.cs

@ -1,12 +1,7 @@
using System;
using System.Collections.Generic;
using System.Text;
using System.Threading.Tasks;
using Avalonia;
using Avalonia.Controls.Notifications;
using Avalonia.Diagnostics.ViewModels;
using Avalonia.Threading;
using ReactiveUI;
namespace ControlCatalog.ViewModels
{
@ -14,26 +9,20 @@ namespace ControlCatalog.ViewModels
{
public MainWindowViewModel()
{
this.WhenAnyValue(x => x.NotificationManager).Subscribe(x =>
{
});
Dispatcher.UIThread.InvokeAsync(async () =>
{
await Task.Delay(5000);
NotificationManager.Show(new NotificationViewModel { Title = "Warning", Message = "Please save your work before closing." });
NotificationManager.Show(new NotificationViewModel (NotificationManager) { Title = "Warning", Message = "Did you know that Avalonia now supports Notifications?" });
await Task.Delay(1500);
NotificationManager.Show(new NotificationContent { Message = "Test2", Type = NotificationType.Error });
NotificationManager.Show(new NotificationContent { Title= "Title", Message = "Test2", Type = NotificationType.Error });
await Task.Delay(2000);
NotificationManager.Show(new NotificationContent { Message = "Test3", Type = NotificationType.Warning });
NotificationManager.Show(new NotificationContent { Title = "Title", Message = "Test3", Type = NotificationType.Warning });
await Task.Delay(2500);
NotificationManager.Show(new NotificationContent { Message = "Test4", Type = NotificationType.Success });
NotificationManager.Show(new NotificationContent { Title = "Title", Message = "Test4", Type = NotificationType.Success });
await Task.Delay(500);
NotificationManager.Show("Test5");

15
samples/ControlCatalog/ViewModels/NotificationViewModel.cs

@ -7,18 +7,25 @@ namespace ControlCatalog.ViewModels
{
public class NotificationViewModel
{
public NotificationViewModel()
public NotificationViewModel(INotificationManager manager)
{
OKCommand = ReactiveCommand.Create(() =>
YesCommand = ReactiveCommand.Create(() =>
{
Application.Current.MainWindow.LocalNotificationManager.Show("Notification Accepted");
manager.Show(new NotificationContent { Title = "Avalonia Notifications", Message = "Start adding notifications to your app today." });
});
NoCommand = ReactiveCommand.Create(() =>
{
manager.Show(new NotificationContent { Title = "Avalonia Notifications", Message = "Start adding notifications to your app today. To find out more visit..." });
});
}
public string Title { get; set; }
public string Message { get; set; }
public ReactiveCommand<Unit, Unit> OKCommand { get; }
public ReactiveCommand<Unit, Unit> YesCommand { get; }
public ReactiveCommand<Unit, Unit> NoCommand { get; }
}
}

8
samples/ControlCatalog/Views/NotificationView.xaml

@ -8,10 +8,10 @@
</Panel>
<DockPanel Grid.Column="1">
<TextBlock DockPanel.Dock="Top" Text="{Binding Title}" FontWeight="Medium" />
<DockPanel LastChildFill="False" DockPanel.Dock="Bottom" Margin="0,8,0,0">
<Button Content="Ok" DockPanel.Dock="Right" Notification.CloseOnClick="True" Command="{Binding OKCommand}" />
<Button Content="Cancel" DockPanel.Dock="Right" Notification.CloseOnClick="True" Margin="0,0,8,0" />
</DockPanel>
<StackPanel Spacing="20" DockPanel.Dock="Bottom" Margin="0,8,0,0">
<Button Content="No" DockPanel.Dock="Right" Notification.CloseOnClick="True" Command="{Binding NoCommand}" Margin="0,0,8,0" />
<Button Content="Yes" DockPanel.Dock="Right" Notification.CloseOnClick="True" Command="{Binding YesCommand}" />
</StackPanel>
<TextBlock Text="{Binding Message}" TextWrapping="Wrap" Opacity=".8" Margin="0,8,0,0"/>
</DockPanel>
</Grid>

2
src/Avalonia.Controls/Notifications/INotificationManager.cs

@ -5,5 +5,7 @@ namespace Avalonia.Controls.Notifications
public interface INotificationManager
{
void Show(object content, TimeSpan? expirationTime = null, Action onClick = null, Action onClose = null);
void Show(NotificationContent content, TimeSpan? expirationTime = null, Action onClick = null, Action onClose = null);
}
}

10
src/Avalonia.Controls/Notifications/Notification.cs

@ -9,6 +9,9 @@ namespace Avalonia.Controls.Notifications
{
public class Notification : ContentControl
{
private bool _isClosed;
private bool _isClosing;
static Notification()
{
IsClosedProperty.Changed.AddClassHandler<Notification>(IsClosedChanged);
@ -41,8 +44,6 @@ namespace Avalonia.Controls.Notifications
});
}
private bool _isClosing;
/// <summary>
/// Determines if the notification is already closing.
/// </summary>
@ -55,8 +56,6 @@ namespace Avalonia.Controls.Notifications
public static readonly DirectProperty<Notification, bool> IsClosingProperty =
AvaloniaProperty.RegisterDirect<Notification, bool>(nameof(IsClosing), o => o.IsClosing);
private bool _isClosed;
/// <summary>
/// Determines if the notification is closed.
/// </summary>
@ -66,6 +65,9 @@ namespace Avalonia.Controls.Notifications
set { SetAndRaise(IsClosedProperty, ref _isClosed, value); }
}
/// <summary>
/// Defines the <see cref="IsClosed"/> property.
/// </summary>
public static readonly DirectProperty<Notification, bool> IsClosedProperty =
AvaloniaProperty.RegisterDirect<Notification, bool>(nameof(IsClosed), o => o.IsClosed, (o, v) => o.IsClosed = v);

9
src/Avalonia.Controls/Notifications/NotificationArea.cs

@ -29,10 +29,6 @@ namespace Avalonia.Controls.Notifications
public static readonly AvaloniaProperty MaxItemsProperty =
AvaloniaProperty.Register<NotificationArea, int>(nameof(MaxItems), int.MaxValue);
public NotificationArea()
{
}
static NotificationArea()
{
PseudoClass<NotificationArea, NotificationPosition>(PositionProperty, x => x == NotificationPosition.TopLeft, ":topleft");
@ -52,6 +48,11 @@ namespace Avalonia.Controls.Notifications
_items = itemsControl?.Children;
}
public void Show(NotificationContent content, TimeSpan? expirationTime, Action onClick, Action onClose)
{
Show(content as object, expirationTime, onClick, onClose);
}
public async void Show(object content, TimeSpan? expirationTime, Action onClick, Action onClose)
{
var notification = new Notification

6
src/Avalonia.Controls/Notifications/NotificationContent.cs

@ -4,6 +4,12 @@ using System.Text;
namespace Avalonia.Controls.Notifications
{
/// <summary>
/// Defines content for a <see cref="Notification"/> control.
/// </summary>
/// <remarks>
/// This notification content type is compatible with native notifications.
/// </remarks>
public class NotificationContent
{
public string Title { get; set; }

8
src/Avalonia.Controls/TopLevel.cs

@ -51,8 +51,8 @@ namespace Avalonia.Controls
/// <summary>
/// Defines the <see cref="LocalNotificationManager"/> property.
/// </summary>
public static readonly DirectProperty<TopLevel, INotificationManager> LocalNotificationManagerProperty =
AvaloniaProperty.RegisterDirect<TopLevel, INotificationManager>(nameof(LocalNotificationManager), o => o.LocalNotificationManager, (o, v) => o.LocalNotificationManager = v);
public static readonly DirectProperty<TopLevel, NotificationArea> LocalNotificationManagerProperty =
AvaloniaProperty.RegisterDirect<TopLevel, NotificationArea>(nameof(LocalNotificationManager), o => o.LocalNotificationManager, (o, v) => o.LocalNotificationManager = v);
/// <summary>
/// Defines the <see cref="SystemNotificationManager"/> property.
@ -66,7 +66,7 @@ namespace Avalonia.Controls
private readonly IApplicationLifecycle _applicationLifecycle;
private readonly IPlatformRenderInterface _renderInterface;
private Size _clientSize;
private INotificationManager _localNotificationManager;
private NotificationArea _localNotificationManager;
private INotificationManager _systemNotificationManager;
private ILayoutManager _layoutManager;
@ -184,7 +184,7 @@ namespace Avalonia.Controls
/// <summary>
/// Gets or sets the Local (in window managed) notification manager.
/// </summary>
public INotificationManager LocalNotificationManager
public NotificationArea LocalNotificationManager
{
get => _localNotificationManager;
protected set => SetAndRaise(LocalNotificationManagerProperty, ref _localNotificationManager, value);

51
src/Avalonia.Themes.Default/NotificationArea.xaml

@ -6,17 +6,10 @@
<StackPanel Name="PART_Items">
<StackPanel.DataTemplates>
<DataTemplate DataType="NotificationContent">
<Border Padding="12" MinHeight="80">
<Grid ColumnDefinitions="Auto,*">
<ContentControl Margin="0,0,12,0" Width="25" Height="25" VerticalAlignment="Top">
<ContentControl HorizontalAlignment="Center" VerticalAlignment="Center"/>
</ContentControl>
<DockPanel Grid.Column="1">
<TextBlock DockPanel.Dock="Top" Text="{Binding Title}" FontWeight="Medium" />
<TextBlock Text="{Binding Message}" TextWrapping="Wrap" Opacity=".8" Margin="0,0,12,0"/>
</DockPanel>
</Grid>
</Border>
<StackPanel Spacing="8">
<TextBlock DockPanel.Dock="Top" Text="{Binding Title}" FontWeight="Medium" />
<TextBlock MaxHeight="80" Text="{Binding Message}" TextWrapping="Wrap" Opacity=".8" Margin="0,0,12,0"/>
</StackPanel>
</DataTemplate>
</StackPanel.DataTemplates>
</StackPanel>
@ -33,7 +26,11 @@
<Setter Property="Template">
<ControlTemplate>
<LayoutTransformControl Name="PART_LayoutTransformControl" UseRenderTransform="True">
<Border Background="{TemplateBinding Background}" BorderBrush="{TemplateBinding BorderBrush}" BorderThickness="{TemplateBinding BorderThickness}" Margin="8,8,0,0">
<Border Background="{TemplateBinding Background}"
BorderBrush="{TemplateBinding BorderBrush}"
BorderThickness="{TemplateBinding BorderThickness}"
Margin="8,8,0,0"
Padding="12">
<ContentControl MinHeight="150" Content="{TemplateBinding Content}" />
</Border>
</LayoutTransformControl>
@ -41,15 +38,15 @@
</Setter>
<Style.Animations>
<Animation Duration="0:0:0.35" Easing="QuadraticEaseIn" FillMode="Forward">
<Animation Duration="0:0:0.45" Easing="QuadraticEaseIn" FillMode="Forward">
<KeyFrame Cue="0%">
<Setter Property="Opacity" Value="0"/>
<Setter Property="TranslateTransform.Y" Value="-20"/>
<Setter Property="TranslateTransform.Y" Value="20"/>
<Setter Property="ScaleTransform.ScaleX" Value="0.85"/>
<Setter Property="ScaleTransform.ScaleY" Value="0.85"/>
</KeyFrame>
<KeyFrame Cue="30%">
<Setter Property="TranslateTransform.Y" Value="20"/>
<Setter Property="TranslateTransform.Y" Value="-20"/>
</KeyFrame>
<KeyFrame Cue="100%">
<Setter Property="Opacity" Value="1"/>
@ -64,14 +61,18 @@
<Style Selector="Notification[IsClosing=true] /template/ LayoutTransformControl#PART_LayoutTransformControl">
<Setter Property="RenderTransformOrigin" Value="50%,0%"/>
<Style.Animations>
<Animation Duration="0:0:0.25" Easing="QuadraticEaseOut" FillMode="Forward">
<Animation Duration="0:0:0.75" Easing="QuadraticEaseOut" FillMode="Forward">
<KeyFrame Cue="0%">
<Setter Property="Opacity" Value="1"/>
<Setter Property="TranslateTransform.X" Value="0"/>
<Setter Property="ScaleTransform.ScaleY" Value="1"/>
</KeyFrame>
<KeyFrame Cue="70%">
<Setter Property="TranslateTransform.X" Value="800"/>
<Setter Property="ScaleTransform.ScaleY" Value="1"/>
</KeyFrame>
<KeyFrame Cue="100%">
<Setter Property="Opacity" Value="0"/>
<Setter Property="ScaleTransform.ScaleY" Value="0"/>
<Setter Property="TranslateTransform.X" Value="800"/>
</KeyFrame>
</Animation>
</Style.Animations>
@ -79,7 +80,7 @@
<Style Selector="Notification[IsClosing=true]">
<Style.Animations>
<Animation Duration="0:0:0.25" Easing="QuadraticEaseOut" FillMode="Forward">
<Animation Duration="0:0:1.25" Easing="QuadraticEaseOut" FillMode="Forward">
<KeyFrame Cue="100%">
<Setter Property="IsClosed" Value="True"/>
</KeyFrame>
@ -98,25 +99,17 @@
<Setter Property="HorizontalAlignment" Value="Right"/>
<Setter Property="VerticalAlignment" Value="Top"/>
</Style>
<Style Selector="Notification">
<!--<Setter TargetName="Icon" Property="Content" Value="{StaticResource InfoIcon}"/>-->
<Setter Property="Background" Value="#444444"/>
</Style>
<Style Selector="Notification:information">
<!--<Setter TargetName="Icon" Property="Content" Value="{StaticResource InfoIcon}"/>-->
<Setter Property="Background" Value="CornflowerBlue"/>
<Setter Property="Background" Value="Teal"/>
</Style>
<Style Selector="Notification:success">
<!--<Setter TargetName="Icon" Property="Content" Value="{StaticResource InfoIcon}"/>-->
<Setter Property="Background" Value="LimeGreen"/>
</Style>
<Style Selector="Notification:warning">
<!--<Setter TargetName="Icon" Property="Content" Value="{StaticResource InfoIcon}"/>-->
<Setter Property="Background" Value="Orange"/>
</Style>
<Style Selector="Notification:error">
<!--<Setter TargetName="Icon" Property="Content" Value="{StaticResource InfoIcon}"/>-->
<Setter Property="Background" Value="OrangeRed"/>
</Style>

Loading…
Cancel
Save