Browse Source

further progress on notifications ui

pull/2453/head
Dan Walmsley 8 years ago
parent
commit
d80083f2f5
  1. 5
      samples/ControlCatalog/MainWindow.xaml
  2. 25
      samples/ControlCatalog/MainWindow.xaml.cs
  3. 38
      src/Avalonia.Controls/Notifications/Notification.cs
  4. 24
      src/Avalonia.Controls/Notifications/NotificationArea.cs
  5. 21
      src/Avalonia.Controls/Notifications/NotificationContent.cs
  6. 2
      src/Avalonia.Controls/Notifications/NotificationManager.cs
  7. 3
      src/Avalonia.Controls/Properties/AssemblyInfo.cs
  8. 14
      src/Avalonia.Themes.Default/Avalonia.Themes.Default.csproj
  9. 1
      src/Avalonia.Themes.Default/DefaultTheme.xaml
  10. 87
      src/Avalonia.Themes.Default/NotificationArea.xaml

5
samples/ControlCatalog/MainWindow.xaml

@ -4,5 +4,8 @@
xmlns:local="clr-namespace:ControlCatalog" xmlns:local="clr-namespace:ControlCatalog"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
x:Class="ControlCatalog.MainWindow"> x:Class="ControlCatalog.MainWindow">
<local:MainView/> <Panel>
<local:MainView/>
<NotificationArea Name="Main" Position="TopRight" MaxItems="5" />
</Panel>
</Window> </Window>

25
samples/ControlCatalog/MainWindow.xaml.cs

@ -1,18 +1,43 @@
using Avalonia; using Avalonia;
using Avalonia.Controls; using Avalonia.Controls;
using Avalonia.Controls.Notifications;
using Avalonia.Markup.Xaml; using Avalonia.Markup.Xaml;
using Avalonia.Threading;
using System; using System;
using System.Threading.Tasks;
namespace ControlCatalog namespace ControlCatalog
{ {
public class MainWindow : Window public class MainWindow : Window
{ {
private readonly NotificationManager _notificationManager = new NotificationManager();
public MainWindow() public MainWindow()
{ {
this.InitializeComponent(); this.InitializeComponent();
this.AttachDevTools(); this.AttachDevTools();
//Renderer.DrawFps = true; //Renderer.DrawFps = true;
//Renderer.DrawDirtyRects = Renderer.DrawFps = true; //Renderer.DrawDirtyRects = Renderer.DrawFps = true;
Dispatcher.UIThread.InvokeAsync(async () =>
{
await Task.Delay(5000);
_notificationManager.Show(new NotificationContent { Message = "Test1", Type = NotificationType.Information }, "Main");
await Task.Delay(500);
_notificationManager.Show(new NotificationContent { Message = "Test2", Type = NotificationType.Error }, "Main");
await Task.Delay(500);
_notificationManager.Show(new NotificationContent { Message = "Test3", Type = NotificationType.Warning }, "Main");
await Task.Delay(500);
_notificationManager.Show(new NotificationContent { Message = "Test4", Type = NotificationType.Success }, "Main");
await Task.Delay(500);
_notificationManager.Show("Test5", "Main");
});
} }
private void InitializeComponent() private void InitializeComponent()

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

@ -1,4 +1,5 @@
using System; using System;
using System.Reactive.Linq;
using System.Threading.Tasks; using System.Threading.Tasks;
using Avalonia.Controls.Primitives; using Avalonia.Controls.Primitives;
using Avalonia.Interactivity; using Avalonia.Interactivity;
@ -11,7 +12,34 @@ namespace Avalonia.Controls.Notifications
static Notification() static Notification()
{ {
CloseOnClickProperty.Changed.AddClassHandler<Button>(CloseOnClickChanged); //CloseOnClickProperty.Changed.AddClassHandler<Button>(CloseOnClickChanged);
}
public Notification()
{
this.GetObservable(ContentProperty)
.OfType<NotificationContent>()
.Subscribe(x =>
{
switch (x.Type)
{
case NotificationType.Error:
PseudoClasses.Add(":error");
break;
case NotificationType.Information:
PseudoClasses.Add(":information");
break;
case NotificationType.Success:
PseudoClasses.Add(":success");
break;
case NotificationType.Warning:
PseudoClasses.Add(":warning");
break;
}
});
} }
public bool IsClosing { get; set; } public bool IsClosing { get; set; }
@ -43,7 +71,7 @@ namespace Avalonia.Controls.Notifications
remove { RemoveHandler(NotificationClosedEvent, value); } remove { RemoveHandler(NotificationClosedEvent, value); }
} }
public static bool GetCloseOnClick(Notification obj) /*public static bool GetCloseOnClick(Notification obj)
{ {
return (bool)obj.GetValue(CloseOnClickProperty); return (bool)obj.GetValue(CloseOnClickProperty);
} }
@ -51,10 +79,10 @@ namespace Avalonia.Controls.Notifications
public static void SetCloseOnClick(Notification obj, bool value) public static void SetCloseOnClick(Notification obj, bool value)
{ {
obj.SetValue(CloseOnClickProperty, value); obj.SetValue(CloseOnClickProperty, value);
} }*/
public static readonly AvaloniaProperty CloseOnClickProperty = //public static readonly AvaloniaProperty CloseOnClickProperty =
AvaloniaProperty.RegisterDirect<Notification, bool>("CloseOnClick", GetCloseOnClick, SetCloseOnClick); // AvaloniaProperty.RegisterDirect<Notification, bool>("CloseOnClick", GetCloseOnClick, SetCloseOnClick);
private static void CloseOnClickChanged(Button dependencyObject, AvaloniaPropertyChangedEventArgs dependencyPropertyChangedEventArgs) private static void CloseOnClickChanged(Button dependencyObject, AvaloniaPropertyChangedEventArgs dependencyPropertyChangedEventArgs)
{ {

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

@ -1,5 +1,7 @@
using System; using System;
using System.Collections; using System.Collections;
using System.Linq;
using System.Threading.Tasks;
using Avalonia.Controls.Primitives; using Avalonia.Controls.Primitives;
using Avalonia.Interactivity; using Avalonia.Interactivity;
@ -15,7 +17,7 @@ namespace Avalonia.Controls.Notifications
set { SetValue(PositionProperty, value); } set { SetValue(PositionProperty, value); }
} }
public static readonly AvaloniaProperty PositionProperty = public static readonly StyledProperty<NotificationPosition> PositionProperty =
AvaloniaProperty.Register<NotificationArea, NotificationPosition>(nameof(Position), NotificationPosition.BottomRight); AvaloniaProperty.Register<NotificationArea, NotificationPosition>(nameof(Position), NotificationPosition.BottomRight);
public int MaxItems public int MaxItems
@ -32,11 +34,19 @@ namespace Avalonia.Controls.Notifications
NotificationManager.AddArea(this); NotificationManager.AddArea(this);
} }
static NotificationArea()
{
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");
}
protected override void OnTemplateApplied(TemplateAppliedEventArgs e) protected override void OnTemplateApplied(TemplateAppliedEventArgs e)
{ {
base.OnTemplateApplied(e); base.OnTemplateApplied(e);
var itemsControl = this.FindControl<Panel>("PART_Items"); var itemsControl = e.NameScope.Find<Panel>("PART_Items");
_items = itemsControl?.Children; _items = itemsControl?.Children;
} }
@ -58,17 +68,17 @@ namespace Avalonia.Controls.Notifications
notification.NotificationClosed += (sender, args) => onClose?.Invoke(); notification.NotificationClosed += (sender, args) => onClose?.Invoke();
notification.NotificationClosed += OnNotificationClosed; notification.NotificationClosed += OnNotificationClosed;
/* if (!IsLoaded) /*if (!this.)
{ {
return; return;
} }*/
var w = Window.GetWindow(this); /*var w = this.VisualRoot Window.GetWindow(this);
var x = PresentationSource.FromVisual(w); var x = PresentationSource.FromVisual(w);
if (x == null) if (x == null)
{ {
return; return;
} }*/
lock (_items) lock (_items)
{ {
@ -86,7 +96,7 @@ namespace Avalonia.Controls.Notifications
} }
await Task.Delay(expirationTime); await Task.Delay(expirationTime);
notification.Close();*/ notification.Close();
} }
private void OnNotificationClosed(object sender, RoutedEventArgs routedEventArgs) private void OnNotificationClosed(object sender, RoutedEventArgs routedEventArgs)

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

@ -0,0 +1,21 @@
using System;
using System.Collections.Generic;
using System.Text;
namespace Avalonia.Controls.Notifications
{
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
}
}

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

@ -26,7 +26,7 @@ namespace Avalonia.Controls.Notifications
} }
if (expirationTime == null) if (expirationTime == null)
expirationTime = TimeSpan.FromSeconds(5); expirationTime = TimeSpan.FromSeconds(25);
if (areaName == string.Empty && _window == null) if (areaName == string.Empty && _window == null)
{ {

3
src/Avalonia.Controls/Properties/AssemblyInfo.cs

@ -14,4 +14,5 @@ using Avalonia.Metadata;
[assembly: XmlnsDefinition("https://github.com/avaloniaui", "Avalonia.Controls.Presenters")] [assembly: XmlnsDefinition("https://github.com/avaloniaui", "Avalonia.Controls.Presenters")]
[assembly: XmlnsDefinition("https://github.com/avaloniaui", "Avalonia.Controls.Primitives")] [assembly: XmlnsDefinition("https://github.com/avaloniaui", "Avalonia.Controls.Primitives")]
[assembly: XmlnsDefinition("https://github.com/avaloniaui", "Avalonia.Controls.Shapes")] [assembly: XmlnsDefinition("https://github.com/avaloniaui", "Avalonia.Controls.Shapes")]
[assembly: XmlnsDefinition("https://github.com/avaloniaui", "Avalonia.Controls.Templates")] [assembly: XmlnsDefinition("https://github.com/avaloniaui", "Avalonia.Controls.Templates")]
[assembly: XmlnsDefinition("https://github.com/avaloniaui", "Avalonia.Controls.Notifications")]

14
src/Avalonia.Themes.Default/Avalonia.Themes.Default.csproj

@ -12,10 +12,18 @@
<ProjectReference Include="..\Avalonia.Layout\Avalonia.Layout.csproj" /> <ProjectReference Include="..\Avalonia.Layout\Avalonia.Layout.csproj" />
<ProjectReference Include="..\Avalonia.Visuals\Avalonia.Visuals.csproj" /> <ProjectReference Include="..\Avalonia.Visuals\Avalonia.Visuals.csproj" />
<ProjectReference Include="..\Avalonia.Styling\Avalonia.Styling.csproj" /> <ProjectReference Include="..\Avalonia.Styling\Avalonia.Styling.csproj" />
<AvaloniaResource Include="DefaultTheme.xaml"/> <AvaloniaResource Include="DefaultTheme.xaml" />
<AvaloniaResource Include="Accents/*.xaml"/> <AvaloniaResource Include="Accents/*.xaml" />
</ItemGroup>
<ItemGroup>
<None Remove="NotificationArea.xaml" />
</ItemGroup> </ItemGroup>
<Import Project="..\..\build\EmbedXaml.props" /> <Import Project="..\..\build\EmbedXaml.props" />
<Import Project="..\..\build\BuildTargets.targets"/> <Import Project="..\..\build\BuildTargets.targets" />
<Import Project="..\..\build\Rx.props" /> <Import Project="..\..\build\Rx.props" />
<ItemGroup>
<EmbeddedResource Update="NotificationArea.xaml">
<Generator>MSBuild:Compile</Generator>
</EmbeddedResource>
</ItemGroup>
</Project> </Project>

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

@ -46,4 +46,5 @@
<StyleInclude Source="resm:Avalonia.Themes.Default.ButtonSpinner.xaml?assembly=Avalonia.Themes.Default"/> <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.NumericUpDown.xaml?assembly=Avalonia.Themes.Default"/>
<StyleInclude Source="resm:Avalonia.Themes.Default.AutoCompleteBox.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"/>
</Styles> </Styles>

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

@ -0,0 +1,87 @@
<Styles xmlns="https://github.com/avaloniaui">
<Style Selector="NotificationArea">
<Setter Property="Margin" Value="0 0 8 8"/>
<Setter Property="Template">
<ControlTemplate>
<StackPanel Name="PART_Items" />
</ControlTemplate>
</Setter>
</Style>
<Style Selector="Notification">
<Setter Property="UseLayoutRounding" Value="True"/>
<Setter Property="Width" Value="350"/>
<Setter Property="FontSize" Value="14"/>
<Setter Property="Foreground" Value="White"/>
<!-- <Setter Property="ContentTemplateSelector" Value="{StaticResource NotificationTemplateSelector}"/> -->
<Setter Property="Template">
<ControlTemplate>
<Border Background="{TemplateBinding Background}"
BorderBrush="{TemplateBinding BorderBrush}"
BorderThickness="{TemplateBinding BorderThickness}"
Margin="8,8,0,0">
<Grid>
<ContentPresenter Content="{TemplateBinding Content}" />
<Button Name="PART_CloseButton" Margin="12" Foreground="{TemplateBinding Foreground}" Opacity="0.8"/>
</Grid>
</Border>
</ControlTemplate>
</Setter>
</Style>
<Style Selector="Notification /template/ Button#PART_CloseButton">
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="Button">
<TextBlock Text="X" FontSize="12" />
</ControlTemplate>
</Setter.Value>
</Setter>
<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"/>
</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>
<Style Selector="NotificationArea:topleft /template/ StackPanel#PART_Items">
<Setter Property="VerticalAlignment" Value="Top"/>
<Setter Property="HorizontalAlignment" Value="Left"/>
</Style>
<Style Selector="NotificationArea:topright /template/ StackPanel#PART_Items">
<Setter Property="VerticalAlignment" Value="Top"/>
<Setter Property="HorizontalAlignment" Value="Right"/>
</Style>
<Style Selector="NotificationArea: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">
<Setter Property="ReverseOrder" Value="True"/>
<Setter Property="VerticalAlignment" Value="Bottom"/>
<Setter Property="HorizontalAlignment" Value="Right"/>
</Style>
</Styles>
Loading…
Cancel
Save