Browse Source

suggested api changes

pull/2453/head
Dan Walmsley 8 years ago
parent
commit
e45805aa50
  1. 4
      samples/ControlCatalog/MainWindow.xaml.cs
  2. 14
      samples/ControlCatalog/ViewModels/MainWindowViewModel.cs
  3. 5
      samples/ControlCatalog/ViewModels/NotificationViewModel.cs
  4. 22
      src/Avalonia.Controls/Notifications/INotificationManager.cs
  5. 2
      src/Avalonia.Controls/Notifications/Notification.cs
  6. 27
      src/Avalonia.Controls/Notifications/NotificationContent.cs
  7. 56
      src/Avalonia.Controls/Notifications/SimpleNotification.cs
  8. 55
      src/Avalonia.Controls/Notifications/WindowNotificationManager.cs
  9. 5
      src/Avalonia.Themes.Default/Avalonia.Themes.Default.csproj
  10. 2
      src/Avalonia.Themes.Default/DefaultTheme.xaml
  11. 12
      src/Avalonia.Themes.Default/WindowNotificationManager.xaml

4
samples/ControlCatalog/MainWindow.xaml.cs

@ -12,7 +12,7 @@ namespace ControlCatalog
{
public class MainWindow : Window
{
private NotificationArea _notificationArea;
private WindowNotificationManager _notificationArea;
public MainWindow()
{
@ -21,7 +21,7 @@ namespace ControlCatalog
//Renderer.DrawFps = true;
//Renderer.DrawDirtyRects = Renderer.DrawFps = true;
_notificationArea = new NotificationArea
_notificationArea = new WindowNotificationManager
{
Position = NotificationPosition.TopRight,
MaxItems = 3

14
samples/ControlCatalog/ViewModels/MainWindowViewModel.cs

@ -1,15 +1,15 @@
using System.Reactive;
using System.Threading.Tasks;
using Avalonia.Controls.Notifications;
using Avalonia.Diagnostics.ViewModels;
using Avalonia.Threading;
using ReactiveUI;
namespace ControlCatalog.ViewModels
{
class MainWindowViewModel : ViewModelBase
{
public MainWindowViewModel(INotificationManager notificationManager)
private IManagedNotificationManager _notificationManager;
public MainWindowViewModel(IManagedNotificationManager notificationManager)
{
_notificationManager = notificationManager;
@ -20,18 +20,16 @@ namespace ControlCatalog.ViewModels
ShowManagedNotificationCommand = ReactiveCommand.Create(() =>
{
NotificationManager.Show(new NotificationContent { Title = "Welcome", Message = "Avalonia now supports Notifications.", Type = NotificationType.Information });
NotificationManager.Show(SimpleNotification.Create("Welcome", "Avalonia now supports Notifications.", NotificationType.Information));
});
ShowNativeNotificationCommand = ReactiveCommand.Create(() =>
{
NotificationManager.Show(new NotificationContent { Title = "Error", Message = "Native Notifications are not quite ready. Coming soon.", Type = NotificationType.Error });
NotificationManager.Show(SimpleNotification.Create("Error", "Native Notifications are not quite ready. Coming soon.", NotificationType.Error));
});
}
private INotificationManager _notificationManager;
public INotificationManager NotificationManager
public IManagedNotificationManager NotificationManager
{
get { return _notificationManager; }
set { this.RaiseAndSetIfChanged(ref _notificationManager, value); }

5
samples/ControlCatalog/ViewModels/NotificationViewModel.cs

@ -1,5 +1,4 @@
using System.Reactive;
using Avalonia;
using Avalonia.Controls.Notifications;
using ReactiveUI;
@ -11,12 +10,12 @@ namespace ControlCatalog.ViewModels
{
YesCommand = ReactiveCommand.Create(() =>
{
manager.Show(new NotificationContent { Title = "Avalonia Notifications", Message = "Start adding notifications to your app today." });
manager.Show(SimpleNotification.Create("Avalonia Notifications", "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..." });
manager.Show(SimpleNotification.Create("Avalonia Notifications", "Start adding notifications to your app today. To find out more visit..."));
});
}

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

@ -2,10 +2,28 @@
namespace Avalonia.Controls.Notifications
{
public interface INotification
{
string Title { get; }
string Message { get; }
NotificationType Type { get; }
TimeSpan Expiration { get; }
Action OnClick { get; }
Action OnClose { get; }
}
public interface INotificationManager
{
void Show(object content, TimeSpan? expirationTime = null, Action onClick = null, Action onClose = null);
void Show(INotification notification);
}
void Show(NotificationContent content, TimeSpan? expirationTime = null, Action onClick = null, Action onClose = null);
public interface IManagedNotificationManager : INotificationManager
{
void Show(object content);
}
}

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

@ -20,7 +20,7 @@ namespace Avalonia.Controls.Notifications
public Notification()
{
this.GetObservable(ContentProperty)
.OfType<NotificationContent>()
.OfType<SimpleNotification>()
.Subscribe(x =>
{
switch (x.Type)

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

@ -1,27 +0,0 @@
using System;
using System.Collections.Generic;
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; }
public string Message { get; set; }
public NotificationType Type { get; set; }
}
public enum NotificationType
{
Information,
Success,
Warning,
Error
}
}

56
src/Avalonia.Controls/Notifications/SimpleNotification.cs

@ -0,0 +1,56 @@
using System;
using System.Collections.Generic;
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 SimpleNotification : INotification
{
public static INotification Create (
string title,
string message,
NotificationType type = NotificationType.Information,
TimeSpan? expiration = null,
Action onClick = null,
Action onClose = null)
{
var result = new SimpleNotification
{
Title = title,
Message = message,
Type = type,
Expiration = expiration.HasValue ? expiration.Value : TimeSpan.FromSeconds(5),
OnClick = onClick,
OnClose = onClose
};
return result;
}
public string Title { get; private set; }
public string Message { get; private set; }
public NotificationType Type { get; private set; }
public TimeSpan Expiration { get; private set; }
public Action OnClick { get; private set; }
public Action OnClose { get; private set; }
}
public enum NotificationType
{
Information,
Success,
Warning,
Error
}
}

55
src/Avalonia.Controls/Notifications/NotificationArea.cs → src/Avalonia.Controls/Notifications/WindowNotificationManager.cs

@ -8,7 +8,7 @@ using Avalonia.VisualTree;
namespace Avalonia.Controls.Notifications
{
public class NotificationArea : TemplatedControl, INotificationManager
public class WindowNotificationManager : TemplatedControl, IManagedNotificationManager
{
private IList _items;
@ -23,7 +23,7 @@ namespace Avalonia.Controls.Notifications
}
public static readonly AvaloniaProperty<NotificationPosition> PositionProperty =
AvaloniaProperty.RegisterAttached<NotificationArea, TopLevel, NotificationPosition>("Position", defaultValue: NotificationPosition.TopLeft, inherits: true);
AvaloniaProperty.RegisterAttached<WindowNotificationManager, TopLevel, NotificationPosition>("Position", defaultValue: NotificationPosition.TopLeft, inherits: true);
public NotificationPosition Position
{
@ -42,7 +42,7 @@ namespace Avalonia.Controls.Notifications
}
public static readonly AvaloniaProperty<int> MaxItemsProperty =
AvaloniaProperty.RegisterAttached<NotificationArea, TopLevel, int>("Position", defaultValue: 5, inherits: true);
AvaloniaProperty.RegisterAttached<WindowNotificationManager, TopLevel, int>("Position", defaultValue: 5, inherits: true);
public int MaxItems
{
@ -50,15 +50,15 @@ namespace Avalonia.Controls.Notifications
set { SetValue(MaxItemsProperty, value); }
}
static NotificationArea()
static WindowNotificationManager()
{
PseudoClass<NotificationArea, NotificationPosition>(PositionProperty, x => x == NotificationPosition.TopLeft, ":topleft");
PseudoClass<NotificationArea, NotificationPosition>(PositionProperty, x => x == NotificationPosition.TopRight, ":topright");
PseudoClass<NotificationArea, NotificationPosition>(PositionProperty, x => x == NotificationPosition.BottomLeft, ":bottomleft");
PseudoClass<NotificationArea, NotificationPosition>(PositionProperty, x => x == NotificationPosition.BottomRight, ":bottomright");
PseudoClass<WindowNotificationManager, NotificationPosition>(PositionProperty, x => x == NotificationPosition.TopLeft, ":topleft");
PseudoClass<WindowNotificationManager, NotificationPosition>(PositionProperty, x => x == NotificationPosition.TopRight, ":topright");
PseudoClass<WindowNotificationManager, NotificationPosition>(PositionProperty, x => x == NotificationPosition.BottomLeft, ":bottomleft");
PseudoClass<WindowNotificationManager, NotificationPosition>(PositionProperty, x => x == NotificationPosition.BottomRight, ":bottomright");
HorizontalAlignmentProperty.OverrideDefaultValue<NotificationArea>(Layout.HorizontalAlignment.Stretch);
VerticalAlignmentProperty.OverrideDefaultValue<NotificationArea>(Layout.VerticalAlignment.Stretch);
HorizontalAlignmentProperty.OverrideDefaultValue<WindowNotificationManager>(Layout.HorizontalAlignment.Stretch);
VerticalAlignmentProperty.OverrideDefaultValue<WindowNotificationManager>(Layout.VerticalAlignment.Stretch);
}
protected override void OnTemplateApplied(TemplateAppliedEventArgs e)
@ -69,32 +69,39 @@ namespace Avalonia.Controls.Notifications
_items = itemsControl?.Children;
}
public void Show(NotificationContent content, TimeSpan? expirationTime, Action onClick, Action onClose)
public void Show(INotification content)
{
Show(content as object, expirationTime, onClick, onClose);
Show(content as object);
}
public async void Show(object content, TimeSpan? expirationTime, Action onClick, Action onClose)
public async void Show(object content)
{
var notification = new Notification
var notification = content as INotification;
var notificationControl = new Notification
{
Content = content
};
notification.PointerPressed += (sender, args) =>
if (notification != null)
{
notificationControl.NotificationClosed += (sender, args) => notification.OnClose?.Invoke();
}
notificationControl.NotificationClosed += OnNotificationClosed;
notificationControl.PointerPressed += (sender, args) =>
{
if (onClick != null)
if (notification != null && notification.OnClick != null)
{
onClick.Invoke();
notification.OnClick.Invoke();
(sender as Notification)?.Close();
}
};
notification.NotificationClosed += (sender, args) => onClose?.Invoke();
notification.NotificationClosed += OnNotificationClosed;
lock (_items)
{
_items.Add(notification);
_items.Add(notificationControl);
if (_items.OfType<Notification>().Count(i => !i.IsClosing) > MaxItems)
{
@ -102,14 +109,14 @@ namespace Avalonia.Controls.Notifications
}
}
if (expirationTime == TimeSpan.MaxValue)
if (notification != null && notification.Expiration == TimeSpan.MaxValue)
{
return;
}
await Task.Delay(expirationTime ?? TimeSpan.FromSeconds(5));
await Task.Delay(notification?.Expiration ?? TimeSpan.FromSeconds(5));
notification.Close();
notificationControl.Close();
}
private void OnNotificationClosed(object sender, RoutedEventArgs routedEventArgs)
@ -118,7 +125,7 @@ namespace Avalonia.Controls.Notifications
_items.Remove(notification);
}
public void Install(TopLevel host)
public void Install(Window host)
{
var adornerLayer = host.GetVisualDescendants()
.OfType<AdornerDecorator>()

5
src/Avalonia.Themes.Default/Avalonia.Themes.Default.csproj

@ -26,4 +26,9 @@
<Generator>MSBuild:Compile</Generator>
</EmbeddedResource>
</ItemGroup>
<ItemGroup>
<None Update="WindowNotificationManager.xaml">
<Generator>MSBuild:Compile</Generator>
</None>
</ItemGroup>
</Project>

2
src/Avalonia.Themes.Default/DefaultTheme.xaml

@ -46,5 +46,5 @@
<StyleInclude Source="resm:Avalonia.Themes.Default.ButtonSpinner.xaml?assembly=Avalonia.Themes.Default"/>
<StyleInclude Source="resm:Avalonia.Themes.Default.NumericUpDown.xaml?assembly=Avalonia.Themes.Default"/>
<StyleInclude Source="resm:Avalonia.Themes.Default.AutoCompleteBox.xaml?assembly=Avalonia.Themes.Default"/>
<StyleInclude Source="resm:Avalonia.Themes.Default.NotificationArea.xaml?assembly=Avalonia.Themes.Default"/>
<StyleInclude Source="resm:Avalonia.Themes.Default.WindowNotificationManager.xaml?assembly=Avalonia.Themes.Default"/>
</Styles>

12
src/Avalonia.Themes.Default/NotificationArea.xaml → src/Avalonia.Themes.Default/WindowNotificationManager.xaml

@ -1,12 +1,12 @@
<Styles xmlns="https://github.com/avaloniaui"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml">
<Style Selector="NotificationArea">
<Style Selector="WindowNotificationManager">
<Setter Property="Margin" Value="0 0 8 8"/>
<Setter Property="Template">
<ControlTemplate>
<StackPanel Name="PART_Items">
<StackPanel.DataTemplates>
<DataTemplate DataType="NotificationContent">
<DataTemplate DataType="INotification">
<StackPanel Spacing="8" Margin="12">
<TextBlock DockPanel.Dock="Top" Text="{Binding Title}" FontWeight="Medium" />
<TextBlock MaxHeight="80" Text="{Binding Message}" TextWrapping="Wrap" Margin="0,0,12,0"/>
@ -119,23 +119,23 @@
<Setter Property="Background" Value="OrangeRed"/>
</Style>
<Style Selector="NotificationArea:topleft /template/ StackPanel#PART_Items">
<Style Selector="WindowNotificationManager:topleft /template/ StackPanel#PART_Items">
<Setter Property="VerticalAlignment" Value="Top"/>
<Setter Property="HorizontalAlignment" Value="Left"/>
</Style>
<Style Selector="NotificationArea:topright /template/ StackPanel#PART_Items">
<Style Selector="WindowNotificationManager:topright /template/ StackPanel#PART_Items">
<Setter Property="VerticalAlignment" Value="Top"/>
<Setter Property="HorizontalAlignment" Value="Right"/>
</Style>
<Style Selector="NotificationArea:bottomleft /template/ StackPanel#PART_Items">
<Style Selector="WindowNotificationManager:bottomleft /template/ StackPanel#PART_Items">
<Setter Property="ReverseOrder" Value="True"/>
<Setter Property="VerticalAlignment" Value="Bottom"/>
<Setter Property="HorizontalAlignment" Value="Left"/>
</Style>
<Style Selector="NotificationArea:bottomright /template/ StackPanel#PART_Items">
<Style Selector="WindowNotificationManager:bottomright /template/ StackPanel#PART_Items">
<Setter Property="ReverseOrder" Value="True"/>
<Setter Property="VerticalAlignment" Value="Bottom"/>
<Setter Property="HorizontalAlignment" Value="Right"/>
Loading…
Cancel
Save