163 lines
4.6 KiB
C#
163 lines
4.6 KiB
C#
using Lattice.UI.Docking.Abstractions;
|
||
using Lattice.UI.Docking.Services;
|
||
using Microsoft.UI.Xaml;
|
||
using Microsoft.UI.Xaml.Controls;
|
||
using System;
|
||
using System.Threading.Tasks;
|
||
|
||
namespace Lattice.UI.Docking.WinUI.Services;
|
||
|
||
/// <summary>
|
||
/// Реализация UI-сервиса для платформы WinUI.
|
||
/// Инкапсулирует платформенно-зависимые операции, такие как создание окон,
|
||
/// показ диалогов и синхронизация с UI-потоком.
|
||
/// </summary>
|
||
public sealed class WinUIDockUIService : DockUIServiceBase, IDockUIService
|
||
{
|
||
public override object CreateMainWindow(IDockHost host)
|
||
{
|
||
if (host is not FrameworkElement hostElement)
|
||
throw new ArgumentException("Host must be a FrameworkElement", nameof(host));
|
||
|
||
var window = new Window();
|
||
window.Content = hostElement;
|
||
window.AppWindow.Title = "Lattice IDE";
|
||
|
||
// Регистрируем окно в трекере
|
||
Lattice.Themes.WindowTracker.Register(window);
|
||
|
||
return window;
|
||
}
|
||
|
||
public override bool? ShowDialog(string title, object content)
|
||
{
|
||
if (content is not FrameworkElement contentElement)
|
||
return null;
|
||
|
||
var dialog = new ContentDialog
|
||
{
|
||
Title = title,
|
||
Content = contentElement,
|
||
PrimaryButtonText = "OK",
|
||
CloseButtonText = "Cancel",
|
||
XamlRoot = GetActiveXamlRoot()
|
||
};
|
||
|
||
var result = dialog.ShowAsync();
|
||
return result.GetAwaiter().GetResult() switch
|
||
{
|
||
ContentDialogResult.Primary => true,
|
||
ContentDialogResult.Secondary => false,
|
||
_ => null
|
||
};
|
||
}
|
||
|
||
public override void ShowMessage(string message, string caption)
|
||
{
|
||
var dialog = new ContentDialog
|
||
{
|
||
Title = caption,
|
||
Content = new TextBlock { Text = message },
|
||
PrimaryButtonText = "OK",
|
||
XamlRoot = GetActiveXamlRoot()
|
||
};
|
||
|
||
dialog.ShowAsync();
|
||
}
|
||
|
||
public override bool Confirm(string message, string caption)
|
||
{
|
||
var dialog = new ContentDialog
|
||
{
|
||
Title = caption,
|
||
Content = new TextBlock { Text = message },
|
||
PrimaryButtonText = "Yes",
|
||
SecondaryButtonText = "No",
|
||
XamlRoot = GetActiveXamlRoot()
|
||
};
|
||
|
||
var result = dialog.ShowAsync().GetAwaiter().GetResult();
|
||
return result == ContentDialogResult.Primary;
|
||
}
|
||
|
||
public override string? Prompt(string prompt, string? defaultValue = null)
|
||
{
|
||
var textBox = new TextBox
|
||
{
|
||
Text = defaultValue ?? string.Empty,
|
||
Width = 300,
|
||
Height = 32
|
||
};
|
||
|
||
var dialog = new ContentDialog
|
||
{
|
||
Title = prompt,
|
||
Content = textBox,
|
||
PrimaryButtonText = "OK",
|
||
SecondaryButtonText = "Cancel",
|
||
XamlRoot = GetActiveXamlRoot()
|
||
};
|
||
|
||
var result = dialog.ShowAsync().GetAwaiter().GetResult();
|
||
return result == ContentDialogResult.Primary ? textBox.Text : null;
|
||
}
|
||
|
||
public override void InvokeOnUIThread(Action action)
|
||
{
|
||
if (action == null) return;
|
||
|
||
var dispatcherQueue = Microsoft.UI.Dispatching.DispatcherQueue.GetForCurrentThread();
|
||
if (dispatcherQueue.HasThreadAccess)
|
||
{
|
||
action();
|
||
}
|
||
else
|
||
{
|
||
dispatcherQueue.TryEnqueue(() => action());
|
||
}
|
||
}
|
||
|
||
/// <summary>
|
||
/// Выполняет указанную асинхронную функцию в UI-потоке.
|
||
/// </summary>
|
||
public async Task InvokeOnUIThreadAsync(Func<Task> action)
|
||
{
|
||
if (action == null) return;
|
||
|
||
var dispatcherQueue = Microsoft.UI.Dispatching.DispatcherQueue.GetForCurrentThread();
|
||
if (dispatcherQueue.HasThreadAccess)
|
||
{
|
||
await action();
|
||
}
|
||
else
|
||
{
|
||
var tcs = new TaskCompletionSource<bool>();
|
||
dispatcherQueue.TryEnqueue(async () =>
|
||
{
|
||
try
|
||
{
|
||
await action();
|
||
tcs.SetResult(true);
|
||
}
|
||
catch (Exception ex)
|
||
{
|
||
tcs.SetException(ex);
|
||
}
|
||
});
|
||
await tcs.Task;
|
||
}
|
||
}
|
||
|
||
private XamlRoot? GetActiveXamlRoot()
|
||
{
|
||
foreach (var window in Lattice.Themes.WindowTracker.Windows)
|
||
{
|
||
if (window.Content is FrameworkElement element)
|
||
{
|
||
return element.XamlRoot;
|
||
}
|
||
}
|
||
|
||
return null;
|
||
}
|
||
} |