Files
NotificationFlyout/src/NotificationFlyout.Wpf.UI.Controls/XamlHost/NotificationFlyoutXamlHost.cs
T
2021-02-11 15:09:20 +00:00

248 lines
7.8 KiB
C#

using NotificationFlyout.Uwp.UI.Controls;
using NotificationFlyout.Uwp.UI.Extensions;
using NotificationFlyout.Wpf.UI.Extensions;
using NotificationFlyout.Wpf.UI.Helpers;
using System;
using System.Windows;
using System.Windows.Input;
using Windows.UI.Xaml.Controls.Primitives;
namespace NotificationFlyout.Wpf.UI.Controls
{
internal class NotificationFlyoutXamlHost : TransparentXamlHost<NotificationFlyoutHost>
{
private const string ShellTrayHandleName = "Shell_TrayWnd";
private Uwp.UI.Controls.NotificationFlyout _flyout;
private NotificationIconHelper _notificationIconHelper;
private SystemPersonalisationHelper _systemPersonalisationHelper;
private TaskbarHelper _taskbarHelper;
internal event EventHandler ContextMenuRequested;
public void SetFlyout(Uwp.UI.Controls.NotificationFlyout flyout)
{
if (_flyout != null)
{
_flyout.ContentChanged -= OnFlyoutContentChanged;
_flyout.IconSourceChanged -= OnFlyoutIconSourceChanged;
_flyout.RequestedThemeChanged -= OnFlyoutIconSourceChanged;
}
_flyout = flyout;
_flyout.ContentChanged += OnFlyoutContentChanged;
_flyout.IconSourceChanged += OnFlyoutIconSourceChanged;
_flyout.RequestedThemeChanged += OnFlyoutRequestedThemeChanged;
UpdateIcons();
UpdateFlyoutContent();
UpdateRequestedTheme();
}
internal void HideFlyout()
{
var flyoutHost = GetHostContent();
if (flyoutHost != null)
{
flyoutHost.HideFlyout();
}
}
internal void ShowFlyout()
{
var flyoutHost = GetHostContent();
if (flyoutHost != null)
{
var taskbarState = _taskbarHelper.GetCurrentState();
var flyoutPlacement = taskbarState.Position switch
{
TaskbarPosition.Left => FlyoutPlacementMode.Right,
TaskbarPosition.Top => FlyoutPlacementMode.Bottom,
TaskbarPosition.Right => FlyoutPlacementMode.Left,
TaskbarPosition.Bottom => FlyoutPlacementMode.Top,
_ => throw new ArgumentOutOfRangeException(),
};
Activate();
flyoutHost.ShowFlyout(flyoutPlacement);
}
}
protected override void OnContentLoaded()
{
PrepareNotificationIcon();
PrepareTaskbar();
UpdateWindow();
}
protected override void OnDeactivated(EventArgs args)
{
HideFlyout();
}
private void OnFlyoutContentChanged(object sender, EventArgs args)
{
UpdateFlyoutContent();
}
private void OnFlyoutIconSourceChanged(object sender, EventArgs args)
{
UpdateIcons();
}
private void OnFlyoutRequestedThemeChanged(object sender, EventArgs args)
{
UpdateRequestedTheme();
}
private void OnIconInvoked(object sender, NotificationIconInvokedEventArgs args)
{
if (args.MouseButton == MouseButton.Left)
{
ShowFlyout();
}
if (args.MouseButton == MouseButton.Right)
{
ContextMenuRequested?.Invoke(this, EventArgs.Empty);
}
}
private void OnTaskbarChanged(object sender, EventArgs args)
{
UpdateWindow();
}
private void OnThemeChanged(object sender, SystemPersonalisationChangedEventArgs args)
{
UpdateIcons();
}
private void PrepareNotificationIcon()
{
_notificationIconHelper = NotificationIconHelper.Create(this);
_notificationIconHelper.IconInvoked += OnIconInvoked;
_systemPersonalisationHelper = SystemPersonalisationHelper.Create(this);
_systemPersonalisationHelper.ThemeChanged += OnThemeChanged;
UpdateIcons();
}
private void PrepareTaskbar()
{
_taskbarHelper = TaskbarHelper.Create(this);
_taskbarHelper.TaskbarChanged += OnTaskbarChanged;
}
protected override void OnClosed(EventArgs args)
{
_notificationIconHelper.Dispose();
}
private void UpdateFlyoutContent()
{
if (_flyout == null) return;
var content = _flyout.Content;
if (content == null) return;
var flyoutHost = GetHostContent();
if (flyoutHost != null)
{
flyoutHost.Content = content;
}
}
private async void UpdateIcons()
{
if (!IsLoaded) return;
if (_flyout == null) return;
var _defaultIconSource = _flyout.IconSource;
var _lightIconSource = _flyout.LightIconSource;
var shellTrayHandle = WindowHelper.GetHandle(ShellTrayHandleName);
if (shellTrayHandle == null) return;
var dpi = WindowHelper.GetDpi(shellTrayHandle);
var iconSource = _systemPersonalisationHelper.Theme == SystemTheme.Dark ? _defaultIconSource : _lightIconSource;
if (iconSource == null) return;
using var icon = await iconSource.ConvertToIconAsync(dpi);
_notificationIconHelper.SetIcon(icon.Handle);
}
private void UpdateRequestedTheme()
{
if (_flyout == null) return;
var requestedTheme = _flyout.RequestedTheme;
var flyoutHost = GetHostContent();
if (flyoutHost != null)
{
flyoutHost.RequestedTheme = requestedTheme;
}
}
private void UpdateWindow()
{
if (!IsLoaded) return;
var flyoutHost = GetHostContent();
if (flyoutHost == null) return;
var taskbarState = _taskbarHelper.GetCurrentState();
Left = taskbarState.Screen.WorkingArea.Left;
Top = taskbarState.Screen.WorkingArea.Top;
var windowWidth = WindowSize * this.DpiX();
var windowHeight = WindowSize * this.DpiY();
double top, left, height, width;
var taskbarRect = taskbarState.Rect;
switch (taskbarState.Position)
{
case TaskbarPosition.Left:
top = taskbarRect.Bottom - windowHeight;
left = taskbarRect.Right;
height = windowHeight;
width = windowWidth;
break;
case TaskbarPosition.Top:
top = taskbarRect.Bottom;
left = FlowDirection == FlowDirection.RightToLeft ? taskbarRect.Left : taskbarRect.Right - windowWidth;
height = windowHeight;
width = windowWidth;
break;
case TaskbarPosition.Right:
top = taskbarRect.Bottom - windowHeight;
left = taskbarRect.Left - windowWidth;
height = windowHeight;
width = windowWidth;
break;
case TaskbarPosition.Bottom:
top = taskbarRect.Top - windowHeight;
left = FlowDirection == FlowDirection.RightToLeft ? taskbarRect.Left : taskbarRect.Right - windowWidth;
height = windowHeight;
width = windowWidth;
break;
default:
throw new ArgumentOutOfRangeException();
}
this.SetWindowPosition(top, left, height, width);
flyoutHost.SetFlyoutPlacement(taskbarState.Position.ToString());
}
}
}