void Remove(ToastAdorner toast) { var index = _adorners.IndexOf(toast) - 1; if (!_adorners.Remove(toast)) { return; } RemoveDelegate del = _adornerLayer.Remove; Application.Current?.Dispatcher?.Invoke(del, toast); if (!_adorners.Any()) { IsEmpty?.Invoke(this, new EventArgs()); return; } if (index < 0) { return; } MoveBackwards(index); }
void ConfigureLeaveActions(ToastAdorner adorner, ToastAdornerSettings settings, int lifetime, Action leaveAction, Action cancelAction) { if (lifetime - settings.LeaveTime <= 0) { return; } var leaveTimer = new Timer(lifetime - settings.LeaveTime); leaveTimer.Elapsed += (s, e) => { leaveTimer?.Dispose(); leaveTimer = null; void Leave() { leaveAction?.Invoke(); } Application.Current?.Dispatcher?.Invoke((ActionDelegate)Leave); }; if (settings.RefreshLifetimeOnMouseOver) { adorner.MouseEnter += (s, e) => { leaveTimer?.Dispose(); leaveTimer = null; void Cancel() { cancelAction?.Invoke(); } Application.Current?.Dispatcher?.Invoke((ActionDelegate)Cancel); }; adorner.MouseLeave += (s, e) => { leaveTimer = new Timer(lifetime - settings.LeaveTime); leaveTimer.Elapsed += (sender, args) => { leaveTimer?.Dispose(); leaveTimer = null; void Leave() { leaveAction?.Invoke(); } Application.Current?.Dispatcher?.Invoke((ActionDelegate)Leave); }; leaveTimer.Start(); }; } leaveTimer.AutoReset = false; leaveTimer.Start(); }
void Configure(ToastAdorner adorner, ToastAdornerSettings settings, Action clickAction, string title, string message) { ConfigureClose(adorner, settings); ConfigureClickAction(adorner, settings, clickAction); var lifetime = settings.DynamicLifetime ? GetDynamicLifetime(settings, title, message) : settings.Lifetime; ConfigureRemove(adorner, settings, lifetime); ConfigureLeave(adorner, settings, lifetime); }
void CancelFade(ToastAdorner adorner, double originalOpacity) { void Animate() { adorner.BeginAnimation(UIElement.OpacityProperty, null); } Application.Current?.Dispatcher?.Invoke((ActionDelegate)Animate); adorner.Opacity = originalOpacity; }
void ConfigureClickAction(ToastAdorner adorner, ToastAdornerSettings settings, Action clickAction) { adorner.ToastView.MouseLeftButtonUp += (s, e) => { clickAction(); if (settings.CloseAfterClickAction) { Remove(adorner); } }; }
void GetLeaveActions(ToastAdorner adorner, ToastAdornerSettings settings, int lifetime, out Action leaveAction, out Action cancelAction) { if (settings.LeaveTime <= 0 || lifetime - settings.LeaveTime <= 0) { leaveAction = null; cancelAction = null; return; } var elapsedStopwatch = new Stopwatch(); double originalOpacity = adorner.Opacity; double originalLeft = adorner.Left; double originalTop = adorner.Top; var isLeaving = false; switch (LeaveStyle) { case LeaveStyle.FadeOut: leaveAction = () => Fade(originalOpacity, settings, adorner); cancelAction = () => CancelFade(adorner, originalOpacity); break; case LeaveStyle.SlideOut: leaveAction = () => { originalLeft = adorner.Left; originalTop = adorner.Top; Slide(adorner, settings); elapsedStopwatch.Start(); isLeaving = true; }; cancelAction = () => { if (!isLeaving) { return; } isLeaving = false; var elapsed = (int)elapsedStopwatch.ElapsedMilliseconds; elapsedStopwatch.Reset(); CancelSlide(adorner, originalLeft, originalTop, elapsed); }; break; case LeaveStyle.None: leaveAction = null; cancelAction = null; break; default: throw new ArgumentOutOfRangeException(); } }
void AddToQueue(ToastAdorner adorner, ToastAdornerSettings toastSettings, Action clickAction, string title, string message) { var queueEntry = new ToastQueueEntry() { Adorner = adorner, Settings = toastSettings, ClickAction = clickAction, Title = title, Message = message }; _queue.Enqueue(queueEntry); }
void ConfigureClose(ToastAdorner adorner, ToastAdornerSettings settings) { if (!settings.CanUserClose) { return; } adorner.CloseRequested += (s, e) => Remove(adorner); if (settings.CloseOnRightClick) { adorner.ToastView.MouseRightButtonUp += (s, e) => Remove(adorner); } }
void Fade(double originalOpacity, ToastAdornerSettings settings, ToastAdorner adorner) { void Animate() { var animation = new DoubleAnimation( originalOpacity, 0, GetLeaveTime(settings), FillBehavior.Stop); adorner.BeginAnimation(UIElement.OpacityProperty, animation); } Application.Current?.Dispatcher?.Invoke((ActionDelegate)Animate); }
void Slide(ToastAdorner adorner, ToastAdornerSettings settings) { double targetTop = 0; double targetLeft = 0; void SetTargets() { targetTop = adorner.Top; targetLeft = adorner.Left; if (LeaveDirection == Direction.Left) { targetLeft = -adorner.ActualWidth; } else if (LeaveDirection == Direction.Right) { targetLeft = GetWidth(); } else if (LeaveDirection == Direction.Up) { targetTop = -adorner.ActualHeight; } else if (LeaveDirection == Direction.Down) { targetTop = GetHeight(); } else { throw new ArgumentOutOfRangeException(); } } Application.Current?.Dispatcher?.Invoke((ActionDelegate)SetTargets); void Animate() { var horizontal = LeaveDirection == Direction.Left || LeaveDirection == Direction.Right; var animation = new DoubleAnimation( horizontal ? adorner.Left : adorner.Top, horizontal ? targetLeft : targetTop, GetLeaveTime(settings), FillBehavior.Stop); adorner.BeginAnimation(horizontal ? ToastAdorner.LeftProperty : ToastAdorner.TopProperty, animation); } Application.Current?.Dispatcher?.Invoke((ActionDelegate)Animate); }
void CancelSlide(ToastAdorner adorner, double originalLeft, double originalTop, int elapsedTime) { void Animate() { var horizontal = LeaveDirection == Direction.Left || LeaveDirection == Direction.Right; adorner.BeginAnimation(horizontal ? ToastAdorner.LeftProperty : ToastAdorner.TopProperty, null); var animation = new DoubleAnimation( horizontal ? adorner.Left : adorner.Top, horizontal ? originalLeft : originalTop, GetCancelTime(elapsedTime)); adorner.BeginAnimation(horizontal ? ToastAdorner.LeftProperty : ToastAdorner.TopProperty, animation); } Application.Current?.Dispatcher?.Invoke((ActionDelegate)Animate); }
public ToastAdorner Show( string message, string title, ToastAdornerSettings toastSettings = null, UIElement toastView = null, Action clickAction = null) { if (toastSettings == null && DefaultToastSettings == null) { throw new ArgumentNullException(nameof(toastSettings), "Toast settings cannot be null if DefaultToastSettings has not been set."); } if (toastSettings == null) { toastSettings = DefaultToastSettings; } if (!toastSettings.CanUserClose && toastSettings.Lifetime <= 0) { throw new InvalidOperationException("Toast is configured to disallow user closing and to never expire."); } ToastAdorner adorner = null; void CreateAdorner() { adorner = new ToastAdorner(ElementToAdorn, toastView ?? _getDefaultView(title, message)); } Application.Current?.Dispatcher?.Invoke((ActionDelegate)CreateAdorner); if (QueueToasts) { AddToQueue(adorner, toastSettings, clickAction, title, message); ProcessQueue(); } else { Configure(adorner, toastSettings, clickAction, title, message); Add(adorner); } return(adorner); }
void ConfigureRemove(ToastAdorner adorner, ToastAdornerSettings settings, int lifetime) { if (lifetime <= 0) { return; } var lifetimeTimer = new Timer(lifetime); lifetimeTimer.Elapsed += (s, e) => { Remove(adorner); lifetimeTimer.Dispose(); }; if (settings.RefreshLifetimeOnMouseOver) { adorner.MouseEnter += (s, e) => lifetimeTimer.Stop(); adorner.MouseLeave += (s, e) => lifetimeTimer.Start(); } lifetimeTimer.AutoReset = false; lifetimeTimer.Start(); }
double GetEntryTop(ToastAdorner adorner) { double top = 0; void GetTop() { if (EnterLocation == Location.TopLeft) { if (EnterFromDirection == Direction.Up) { top = -adorner.ActualHeight; } else if (EnterFromDirection != Direction.Left) { throw new InvalidOperationException(); } } if (EnterLocation == Location.TopRight) { if (EnterFromDirection == Direction.Up) { top = -adorner.ActualHeight; } else if (EnterFromDirection != Direction.Right) { throw new InvalidOperationException(); } } if (EnterLocation == Location.BottomLeft) { if (EnterFromDirection == Direction.Left) { top = GetHeight() - adorner.ActualHeight; } else if (EnterFromDirection == Direction.Down) { top = GetHeight(); } else { throw new InvalidOperationException(); } } if (EnterLocation == Location.BottomRight) { if (EnterFromDirection == Direction.Right) { top = GetHeight() - adorner.ActualHeight; } else if (EnterFromDirection == Direction.Down) { top = GetHeight(); } else { throw new InvalidOperationException(); } } top += VerticalAdjustment; } Application.Current?.Dispatcher?.Invoke((ActionDelegate)GetTop); return(top); }
double GetEntryLeft(ToastAdorner adorner) { double left = 0; void GetLeft() { if (EnterLocation == Location.TopLeft) { if (EnterFromDirection == Direction.Left) { left = -adorner.ActualWidth; } else if (EnterFromDirection != Direction.Up) { throw new InvalidOperationException(); } } if (EnterLocation == Location.BottomLeft) { if (EnterFromDirection == Direction.Left) { left = -adorner.ActualWidth; } else if (EnterFromDirection != Direction.Down) { throw new InvalidOperationException(); } } if (EnterLocation == Location.TopRight) { if (EnterFromDirection == Direction.Right) { left = GetWidth(); } else if (EnterFromDirection == Direction.Up) { left = GetWidth() - adorner.ActualWidth; } else { throw new InvalidOperationException(); } } if (EnterLocation == Location.BottomRight) { if (EnterFromDirection == Direction.Right) { left = GetWidth(); } else if (EnterFromDirection == Direction.Down) { left = GetWidth() - adorner.ActualWidth; } else { throw new InvalidOperationException(); } } left += HorizontalAdjustment; } Application.Current?.Dispatcher?.Invoke((ActionDelegate)GetLeft); return(left); }
void Enter(ToastAdorner toast) { toast.Top = GetEntryTop(toast); toast.Left = GetEntryLeft(toast); if (EnterStyle == EnterStyle.PopIn || EnterStyle == EnterStyle.FadeIn) { if (EnterLocation == Location.TopLeft || EnterLocation == Location.TopRight) { toast.Top += toast.ActualHeight + VerticalPadding; } if (EnterLocation == Location.BottomLeft || EnterLocation == Location.BottomRight) { toast.Top -= toast.ActualHeight + VerticalPadding; } if (EnterLocation == Location.TopLeft || EnterLocation == Location.BottomLeft) { toast.Left += toast.ActualWidth + HorizontalPadding; } if (EnterLocation == Location.TopRight || EnterLocation == Location.BottomRight) { toast.Left -= toast.ActualWidth + HorizontalPadding; } } if (EnterStyle == EnterStyle.FadeIn) { toast.Opacity = 0; void Animate() { var animation = new DoubleAnimation( 0, 1, MoveDuration, FillBehavior.Stop); toast.BeginAnimation(UIElement.OpacityProperty, animation); } Application.Current?.Dispatcher?.Invoke((ActionDelegate)Animate); } if (EnterStyle == EnterStyle.SlideIn) { double from; double target; if (EnterFromDirection == Direction.Left) { from = toast.Left; target = toast.Left + toast.ActualWidth + HorizontalPadding + HorizontalAdjustment; } else if (EnterFromDirection == Direction.Right) { from = toast.Left; target = GetWidth() - toast.ActualWidth - HorizontalPadding + HorizontalAdjustment; } else if (EnterFromDirection == Direction.Up) { from = toast.Top; target = toast.Top + toast.ActualHeight + VerticalPadding + VerticalAdjustment; } else // Direction.Down { from = toast.Top; target = GetHeight() - toast.ActualHeight - VerticalPadding + VerticalAdjustment; } var property = EnterFromDirection == Direction.Left || EnterFromDirection == Direction.Right ? ToastAdorner.LeftProperty : ToastAdorner.TopProperty; var animation = new DoubleAnimation( from, target, MoveDuration); void Animate() { toast.BeginAnimation(property, animation); } Application.Current?.Dispatcher?.Invoke((ActionDelegate)Animate); } if (MoveStyle == MoveStyle.Stack) { if (MoveDirection == Direction.Left) { foreach (var adorner in _adorners) { toast.Left -= adorner.ActualWidth + HorizontalPadding; } } else if (MoveDirection == Direction.Right) { foreach (var adorner in _adorners) { toast.Left += adorner.ActualWidth + HorizontalPadding; } } else if (MoveDirection == Direction.Up) { foreach (var adorner in _adorners) { toast.Top -= adorner.ActualHeight + VerticalPadding; } } else if (MoveDirection == Direction.Down) { foreach (var adorner in _adorners) { toast.Top += adorner.ActualHeight + VerticalPadding; } } } if (MoveStyle == MoveStyle.Stack) { _adorners.Insert(0, toast); } else { _adorners.Add(toast); } if (MoveStyle == MoveStyle.Push) { MoveForward(); } }
void Add(ToastAdorner toast) { toast.Loaded += (s, e) => { Enter(toast); }; _adornerLayer.Add(toast); }
void ConfigureLeave(ToastAdorner adorner, ToastAdornerSettings settings, int lifetime) { GetLeaveActions(adorner, settings, lifetime, out var leaveAction, out var cancelAction); ConfigureLeaveActions(adorner, settings, lifetime, leaveAction, cancelAction); }