From 4f43898d19985ebefb5516a6ea131242cf86a9b7 Mon Sep 17 00:00:00 2001 From: Dan Walmsley Date: Mon, 8 Apr 2019 20:11:34 +0100 Subject: [PATCH 01/70] make stackpanel reversable. --- src/Avalonia.Controls/StackPanel.cs | 19 ++++++++++++++++++- 1 file changed, 18 insertions(+), 1 deletion(-) diff --git a/src/Avalonia.Controls/StackPanel.cs b/src/Avalonia.Controls/StackPanel.cs index df0c113cc0..1f42e5d23e 100644 --- a/src/Avalonia.Controls/StackPanel.cs +++ b/src/Avalonia.Controls/StackPanel.cs @@ -24,6 +24,12 @@ namespace Avalonia.Controls public static readonly StyledProperty OrientationProperty = AvaloniaProperty.Register(nameof(Orientation), Orientation.Vertical); + /// + /// Defines the property. + /// + public static readonly StyledProperty ReverseOrderProperty = + AvaloniaProperty.Register(nameof(ReverseOrder)); + /// /// Initializes static members of the class. /// @@ -51,6 +57,15 @@ namespace Avalonia.Controls set { SetValue(OrientationProperty, value); } } + /// + /// Gets or sets if the child controls will be layed out in reverse order. + /// + public bool ReverseOrder + { + get => GetValue(ReverseOrderProperty); + set => SetValue(ReverseOrderProperty, value); + } + /// /// Gets the next control in the specified direction. /// @@ -244,7 +259,9 @@ namespace Avalonia.Controls arrangedWidth = 0; } - foreach (Control child in Children) + var children = ReverseOrder ? Children.Reverse() : Children; + + foreach (Control child in children) { double childWidth = child.DesiredSize.Width; double childHeight = child.DesiredSize.Height; From b31701d1caa17d72f8d1086690625eac17ab219c Mon Sep 17 00:00:00 2001 From: Dan Walmsley Date: Mon, 8 Apr 2019 20:35:41 +0100 Subject: [PATCH 02/70] begin port of notification controls --- .../Notifications/INotificationManager.cs | 9 ++ .../Notifications/Notification.cs | 101 +++++++++++++++++ .../Notifications/NotificationArea.cs | 106 ++++++++++++++++++ .../Notifications/NotificationManager.cs | 56 +++++++++ 4 files changed, 272 insertions(+) create mode 100644 src/Avalonia.Controls/Notifications/INotificationManager.cs create mode 100644 src/Avalonia.Controls/Notifications/Notification.cs create mode 100644 src/Avalonia.Controls/Notifications/NotificationArea.cs create mode 100644 src/Avalonia.Controls/Notifications/NotificationManager.cs diff --git a/src/Avalonia.Controls/Notifications/INotificationManager.cs b/src/Avalonia.Controls/Notifications/INotificationManager.cs new file mode 100644 index 0000000000..e0b73d6293 --- /dev/null +++ b/src/Avalonia.Controls/Notifications/INotificationManager.cs @@ -0,0 +1,9 @@ +using System; + +namespace Avalonia.Controls.Notifications +{ + interface INotificationManager + { + void Show(object content, string areaName = "", TimeSpan? expirationTime = null, Action onClick = null, Action onClose = null); + } +} diff --git a/src/Avalonia.Controls/Notifications/Notification.cs b/src/Avalonia.Controls/Notifications/Notification.cs new file mode 100644 index 0000000000..f50458163b --- /dev/null +++ b/src/Avalonia.Controls/Notifications/Notification.cs @@ -0,0 +1,101 @@ +using System; +using System.Threading.Tasks; +using Avalonia.Controls.Primitives; +using Avalonia.Interactivity; + +namespace Avalonia.Controls.Notifications +{ + public class Notification : ContentControl + { + private TimeSpan _closingAnimationTime = TimeSpan.Zero; + + public bool IsClosing { get; set; } + + public static readonly RoutedEvent NotificationCloseInvokedEvent = EventManager.RegisterRoutedEvent( + "NotificationCloseInvoked", RoutingStrategy.Bubble, typeof(RoutedEventHandler), typeof(Notification)); + + public static readonly RoutedEvent NotificationClosedEvent = EventManager.RegisterRoutedEvent( + "NotificationClosed", RoutingStrategy.Bubble, typeof(RoutedEventHandler), typeof(Notification)); + + public event RoutedEventHandler NotificationCloseInvoked + { + add { AddHandler(NotificationCloseInvokedEvent, value); } + remove { RemoveHandler(NotificationCloseInvokedEvent, value); } + } + + public event RoutedEventHandler NotificationClosed + { + add { AddHandler(NotificationClosedEvent, value); } + remove { RemoveHandler(NotificationClosedEvent, value); } + } + + public static bool GetCloseOnClick(DependencyObject obj) + { + return (bool)obj.GetValue(CloseOnClickProperty); + } + + public static void SetCloseOnClick(DependencyObject obj, bool value) + { + obj.SetValue(CloseOnClickProperty, value); + } + + public static readonly DependencyProperty CloseOnClickProperty = + DependencyProperty.RegisterAttached("CloseOnClick", typeof(bool), typeof(Notification), new FrameworkPropertyMetadata(false, CloseOnClickChanged)); + + private static void CloseOnClickChanged(DependencyObject dependencyObject, DependencyPropertyChangedEventArgs dependencyPropertyChangedEventArgs) + { + var button = dependencyObject as Button; + if (button == null) + { + return; + } + + var value = (bool)dependencyPropertyChangedEventArgs.NewValue; + + if (value) + { + button.Click += (sender, args) => + { + var notification = VisualTreeHelperExtensions.GetParent(button); + notification?.Close(); + }; + } + } + + protected override void OnTemplateApplied(TemplateAppliedEventArgs e) + { + base.OnTemplateApplied(e); + var closeButton = this.FindControl