Skip to content

Commit

Permalink
[Dev/2.0] close context menu on window events (#845)
Browse files Browse the repository at this point in the history
* [DevToys 2.0] Close context menu on window events

* Added support for MacOS

* removed comment
  • Loading branch information
veler authored Jun 8, 2023
1 parent 3f4cd7d commit 7990ba9
Show file tree
Hide file tree
Showing 9 changed files with 143 additions and 11 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,6 @@

namespace DevToys.Blazor.Components;

// TODO: Close the context menu when the window lose focus or get resized.
public partial class ContextMenu : StyledComponentBase
{
private bool _isOpen;
Expand Down
17 changes: 17 additions & 0 deletions src/app/dev/DevToys.Blazor/Core/Services/ContextMenuService.cs
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,18 @@
public sealed class ContextMenuService
{
private readonly object _lock = new();
private readonly IWindowService _windowService;

public ContextMenuService(IWindowService windowService)
{
Guard.IsNotNull(windowService);
_windowService = windowService;

_windowService.WindowLostFocus += WindowService_MajorWindowChange;
_windowService.WindowClosing += WindowService_MajorWindowChange;
_windowService.WindowLocationChanged += WindowService_MajorWindowChange;
_windowService.WindowSizeChanged += WindowService_MajorWindowChange;
}

internal bool IsContextMenuOpened { get; private set; }

Expand Down Expand Up @@ -39,4 +51,9 @@ internal void OnCloseContextMenuRequested()
{
CloseContextMenuRequested?.Invoke(this, EventArgs.Empty);
}

private void WindowService_MajorWindowChange(object? sender, EventArgs e)
{
OnCloseContextMenuRequested();
}
}
12 changes: 12 additions & 0 deletions src/app/dev/DevToys.Blazor/Core/Services/IWindowService.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
namespace DevToys.Blazor.Core.Services;

public interface IWindowService
{
event EventHandler<EventArgs>? WindowLostFocus;

event EventHandler<EventArgs>? WindowLocationChanged;

event EventHandler<EventArgs>? WindowSizeChanged;

event EventHandler<EventArgs>? WindowClosing;
}
9 changes: 9 additions & 0 deletions src/app/dev/platforms/desktop/DevToys.MacOS/App.xaml.cs
Original file line number Diff line number Diff line change
Expand Up @@ -8,4 +8,13 @@ public App()

MainPage = new MainPage();
}

protected override Window CreateWindow(IActivationState? activationState)
{
Window window = base.CreateWindow(activationState);
window.Width = 800;
window.Height = 600;

return window;
}
}
40 changes: 40 additions & 0 deletions src/app/dev/platforms/desktop/DevToys.MacOS/Core/WindowService.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
using DevToys.Blazor.Core.Services;
using Foundation;

namespace DevToys.MacOS.Core;

internal sealed class WindowService : IWindowService
{
public event EventHandler<EventArgs>? WindowLostFocus;
public event EventHandler<EventArgs>? WindowLocationChanged;
public event EventHandler<EventArgs>? WindowSizeChanged;
public event EventHandler<EventArgs>? WindowClosing;

public WindowService()
{
NSNotificationCenter.DefaultCenter.AddObserver(new NSString("NSWindowDidResignMainNotification"), OnWindowLostFocus);
NSNotificationCenter.DefaultCenter.AddObserver(new NSString("NSWindowWillMoveNotification"), OnWindowLocationChanged);
NSNotificationCenter.DefaultCenter.AddObserver(new NSString("NSWindowWillStartLiveResizeNotification"), OnWindowSizeChanged);
NSNotificationCenter.DefaultCenter.AddObserver(new NSString("NSWindowWillCloseNotification"), OnWindowClosing);
}

public void OnWindowLostFocus(NSNotification notification)
{
WindowLostFocus?.Invoke(this, EventArgs.Empty);
}

public void OnWindowLocationChanged(NSNotification notification)
{
WindowLocationChanged?.Invoke(this, EventArgs.Empty);
}

public void OnWindowSizeChanged(NSNotification notification)
{
WindowSizeChanged?.Invoke(this, EventArgs.Empty);
}

public void OnWindowClosing(NSNotification notification)
{
WindowClosing?.Invoke(this, EventArgs.Empty);
}
}
8 changes: 4 additions & 4 deletions src/app/dev/platforms/desktop/DevToys.MacOS/MauiProgram.cs
Original file line number Diff line number Diff line change
@@ -1,11 +1,10 @@
using DevToys.Api;
using DevToys.Blazor.Core.Languages;
using DevToys.Blazor.Services;
using DevToys.Blazor.Core.Services;
using DevToys.Business.ViewModels;
using DevToys.Core.Logging;
using DevToys.Core.Mef;
using DevToys.MacOS.Core;
using Microsoft.Extensions.DependencyInjection.Extensions;
using Microsoft.Extensions.Logging;
using Uno.Extensions;
using PredefinedSettings = DevToys.Core.Settings.PredefinedSettings;
Expand Down Expand Up @@ -97,8 +96,9 @@ private ServiceProvider InitializeServices(IServiceCollection serviceCollection)
});

serviceCollection.AddSingleton(provider => MefComposer!.Provider);
serviceCollection.TryAddScoped<PopoverService, PopoverService>();
serviceCollection.TryAddScoped<ContextMenuService, ContextMenuService>();
serviceCollection.AddSingleton<IWindowService, WindowService>();
serviceCollection.AddScoped<PopoverService, PopoverService>();
serviceCollection.AddScoped<ContextMenuService, ContextMenuService>();

ServiceProvider serviceProvider = serviceCollection.BuildServiceProvider();

Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,46 @@
using System.Windows;
using DevToys.Blazor.Core.Services;

namespace DevToys.Windows.Core;

internal sealed class WindowService : IWindowService
{
private Window? _window;

public event EventHandler<EventArgs>? WindowLostFocus;
public event EventHandler<EventArgs>? WindowLocationChanged;
public event EventHandler<EventArgs>? WindowSizeChanged;
public event EventHandler<EventArgs>? WindowClosing;

internal void SetWindow(Window window)
{
Guard.IsNull(_window);
Guard.IsNotNull(window);
_window = window;

_window.LostFocus += Window_LostFocus;
_window.LocationChanged += Window_LocationChanged;
_window.SizeChanged += Window_SizeChanged;
_window.Closing += Window_Closing;
}

private void Window_LostFocus(object sender, RoutedEventArgs e)
{
WindowLostFocus?.Invoke(this, EventArgs.Empty);
}

private void Window_LocationChanged(object? sender, EventArgs e)
{
WindowLocationChanged?.Invoke(this, EventArgs.Empty);
}

private void Window_SizeChanged(object sender, SizeChangedEventArgs e)
{
WindowSizeChanged?.Invoke(this, EventArgs.Empty);
}

private void Window_Closing(object? sender, CancelEventArgs e)
{
WindowClosing?.Invoke(this, EventArgs.Empty);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@
xmlns:controls="clr-namespace:DevToys.Windows.Controls"
xmlns:blazor="clr-namespace:Microsoft.AspNetCore.Components.WebView.Wpf;assembly=Microsoft.AspNetCore.Components.WebView.Wpf"
mc:Ignorable="d"
Loaded="MainWindow_Loaded"
Title="MainWindow"
Height="450"
Width="800"
Expand Down
20 changes: 14 additions & 6 deletions src/app/dev/platforms/desktop/DevToys.Windows/MainWindow.xaml.cs
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
using DevToys.Api;
using System;
using DevToys.Api;
using DevToys.Blazor.Core.Languages;
using DevToys.Blazor.Core.Services;
using DevToys.Business.ViewModels;
Expand All @@ -9,7 +10,6 @@
using DevToys.Windows.Core;
using Microsoft.AspNetCore.Components.WebView;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.DependencyInjection.Extensions;
using Microsoft.Extensions.Logging;
using PredefinedSettings = DevToys.Core.Settings.PredefinedSettings;

Expand All @@ -23,6 +23,7 @@ public partial class MainWindow : MicaWindowWithOverlay
private static MainWindow? mainWindowInstance;

private readonly MefComposer _mefComposer;
private readonly ServiceProvider _serviceProvider;
private readonly DateTime _uiLoadingTime;
private ILogger? _logger;

Expand All @@ -33,7 +34,7 @@ public MainWindow()
DateTime startTime = DateTime.Now;

// Initialize services and logging.
ServiceProvider serviceProvider = InitializeServices();
_serviceProvider = InitializeServices();

// Listen for unhandled exceptions.
AppDomain.CurrentDomain.UnhandledException += OnUnhandledException;
Expand All @@ -58,7 +59,7 @@ LanguageDefinition languageDefinition
LanguageManager.Instance.SetCurrentCulture(languageDefinition);

// Load the UI.
Resources.Add("services", serviceProvider);
Resources.Add("services", _serviceProvider);
InitializeComponent();

_themeListener = _mefComposer.Provider.Import<IThemeListener>();
Expand All @@ -68,6 +69,12 @@ LanguageDefinition languageDefinition
blazorWebView.BlazorWebViewInitialized += BlazorWebView_BlazorWebViewInitialized;
}

private void MainWindow_Loaded(object sender, System.Windows.RoutedEventArgs e)
{
var windowService = (WindowService)_serviceProvider.GetService<IWindowService>()!;
windowService.SetWindow(this);
}

private void BlazorWebView_BlazorWebViewInitializing(object? sender, BlazorWebViewInitializingEventArgs e)
{
// Set the web view transparent.
Expand Down Expand Up @@ -113,8 +120,9 @@ private ServiceProvider InitializeServices()
});

serviceCollection.AddSingleton(provider => _mefComposer.Provider);
serviceCollection.TryAddScoped<PopoverService, PopoverService>();
serviceCollection.TryAddScoped<ContextMenuService, ContextMenuService>();
serviceCollection.AddSingleton<IWindowService, WindowService>();
serviceCollection.AddScoped<PopoverService, PopoverService>();
serviceCollection.AddScoped<ContextMenuService, ContextMenuService>();

ServiceProvider serviceProvider = serviceCollection.BuildServiceProvider();

Expand Down

0 comments on commit 7990ba9

Please sign in to comment.