2026-04-02 21:12:06 +08:00
|
|
|
|
using System;
|
2026-04-03 11:42:00 +08:00
|
|
|
|
using Avalonia;
|
2026-04-02 21:12:06 +08:00
|
|
|
|
using Avalonia.Controls;
|
2026-04-10 22:13:53 +08:00
|
|
|
|
using Avalonia.Input;
|
2026-04-02 21:12:06 +08:00
|
|
|
|
using Avalonia.Interactivity;
|
2026-04-03 01:17:47 +08:00
|
|
|
|
using LanMountainDesktop.ComponentSystem;
|
2026-04-02 21:12:06 +08:00
|
|
|
|
using LanMountainDesktop.Services;
|
2026-04-03 01:17:47 +08:00
|
|
|
|
using LanMountainDesktop.Services.Settings;
|
2026-04-03 13:14:20 +08:00
|
|
|
|
using Avalonia.Controls.ApplicationLifetimes;
|
2026-04-02 21:12:06 +08:00
|
|
|
|
|
|
|
|
|
|
namespace LanMountainDesktop.Views;
|
|
|
|
|
|
|
|
|
|
|
|
/// <summary>
|
|
|
|
|
|
/// 融合桌面组件库窗口 - 专门用于添加组件到系统桌面(负一屏)
|
|
|
|
|
|
///
|
|
|
|
|
|
/// 注意:此窗口只能添加组件到融合桌面,不能添加到阑山桌面
|
|
|
|
|
|
/// </summary>
|
|
|
|
|
|
public partial class FusedDesktopComponentLibraryWindow : Window
|
|
|
|
|
|
{
|
|
|
|
|
|
private readonly IFusedDesktopLayoutService _layoutService = FusedDesktopLayoutServiceProvider.GetOrCreate();
|
2026-04-03 01:17:47 +08:00
|
|
|
|
private readonly ISettingsFacadeService _settingsFacade = HostSettingsFacadeProvider.GetOrCreate();
|
2026-04-02 21:12:06 +08:00
|
|
|
|
private TransparentOverlayWindow? _overlayWindow;
|
|
|
|
|
|
|
2026-04-03 01:17:47 +08:00
|
|
|
|
// 与 TransparentOverlayWindow 保持一致的默认 cellSize
|
|
|
|
|
|
private const double DefaultCellSize = 100;
|
|
|
|
|
|
|
2026-04-02 21:12:06 +08:00
|
|
|
|
public FusedDesktopComponentLibraryWindow()
|
|
|
|
|
|
{
|
|
|
|
|
|
InitializeComponent();
|
|
|
|
|
|
|
|
|
|
|
|
LibraryControl.AddComponentRequested += OnAddComponentRequested;
|
2026-04-03 13:14:20 +08:00
|
|
|
|
|
|
|
|
|
|
var mainWindow = (Application.Current?.ApplicationLifetime as IClassicDesktopStyleApplicationLifetime)?.MainWindow as MainWindow;
|
|
|
|
|
|
mainWindow?.RegisterFusedLibraryWindow(this);
|
2026-04-02 21:12:06 +08:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/// <summary>
|
|
|
|
|
|
/// 设置透明覆盖层窗口引用
|
|
|
|
|
|
/// </summary>
|
|
|
|
|
|
public void SetOverlayWindow(TransparentOverlayWindow overlayWindow)
|
|
|
|
|
|
{
|
|
|
|
|
|
_overlayWindow = overlayWindow;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/// <summary>
|
2026-04-03 01:17:47 +08:00
|
|
|
|
/// 添加组件请求处理 - 将组件放置在屏幕(覆盖层画布)中央
|
2026-04-02 21:12:06 +08:00
|
|
|
|
/// </summary>
|
|
|
|
|
|
private void OnAddComponentRequested(object? sender, string componentId)
|
|
|
|
|
|
{
|
|
|
|
|
|
if (_overlayWindow is null)
|
|
|
|
|
|
{
|
|
|
|
|
|
AppLogger.Warn("FusedDesktopLibrary", "Overlay window is not set.");
|
|
|
|
|
|
return;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
2026-04-03 01:17:47 +08:00
|
|
|
|
// 计算组件的像素尺寸
|
|
|
|
|
|
var (componentWidth, componentHeight) = ResolveComponentSize(componentId);
|
|
|
|
|
|
|
|
|
|
|
|
// 取覆盖层画布的中心点,减去组件半尺寸,使组件出现在屏幕正中央
|
|
|
|
|
|
var overlayBounds = _overlayWindow.Bounds;
|
|
|
|
|
|
var centerX = overlayBounds.Width / 2.0 - componentWidth / 2.0;
|
|
|
|
|
|
var centerY = overlayBounds.Height / 2.0 - componentHeight / 2.0;
|
2026-04-02 21:12:06 +08:00
|
|
|
|
|
2026-04-03 01:17:47 +08:00
|
|
|
|
// 边界保护:确保组件不超出屏幕边界
|
|
|
|
|
|
centerX = Math.Max(0, Math.Min(centerX, overlayBounds.Width - componentWidth));
|
|
|
|
|
|
centerY = Math.Max(0, Math.Min(centerY, overlayBounds.Height - componentHeight));
|
2026-04-02 21:12:06 +08:00
|
|
|
|
|
2026-04-03 01:17:47 +08:00
|
|
|
|
_overlayWindow.AddComponent(componentId, centerX, centerY, componentWidth, componentHeight);
|
|
|
|
|
|
|
|
|
|
|
|
AppLogger.Info("FusedDesktopLibrary",
|
|
|
|
|
|
$"Added component '{componentId}' at center ({centerX:F0}, {centerY:F0}) size ({componentWidth}x{componentHeight}).");
|
2026-04-02 21:12:06 +08:00
|
|
|
|
|
|
|
|
|
|
// 关闭窗口
|
|
|
|
|
|
Close();
|
|
|
|
|
|
}
|
|
|
|
|
|
|
2026-04-03 01:17:47 +08:00
|
|
|
|
/// <summary>
|
|
|
|
|
|
/// 解析组件的默认像素尺寸(基于组件定义的 MinCells * DefaultCellSize)
|
|
|
|
|
|
/// </summary>
|
|
|
|
|
|
private (double Width, double Height) ResolveComponentSize(string componentId)
|
|
|
|
|
|
{
|
|
|
|
|
|
try
|
|
|
|
|
|
{
|
|
|
|
|
|
var pluginRuntimeService = (Application.Current as App)?.PluginRuntimeService;
|
|
|
|
|
|
var registry = DesktopComponentRegistryFactory.Create(pluginRuntimeService);
|
|
|
|
|
|
if (registry.TryGetDefinition(componentId, out var definition))
|
|
|
|
|
|
{
|
|
|
|
|
|
var w = Math.Max(1, definition.MinWidthCells) * DefaultCellSize;
|
|
|
|
|
|
var h = Math.Max(1, definition.MinHeightCells) * DefaultCellSize;
|
|
|
|
|
|
return (w, h);
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
catch (Exception ex)
|
|
|
|
|
|
{
|
|
|
|
|
|
AppLogger.Warn("FusedDesktopLibrary", $"Failed to resolve component size for '{componentId}'.", ex);
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
// 回退为 2×2 格子的默认尺寸
|
|
|
|
|
|
return (DefaultCellSize * 2, DefaultCellSize * 2);
|
|
|
|
|
|
}
|
|
|
|
|
|
|
2026-04-02 21:12:06 +08:00
|
|
|
|
private void OnCloseClick(object? sender, RoutedEventArgs e)
|
|
|
|
|
|
{
|
|
|
|
|
|
Close();
|
|
|
|
|
|
}
|
2026-04-10 12:20:05 +08:00
|
|
|
|
|
2026-04-10 22:13:53 +08:00
|
|
|
|
private void OnWindowTitleBarPointerPressed(object? sender, PointerPressedEventArgs e)
|
2026-04-10 12:20:05 +08:00
|
|
|
|
{
|
2026-04-10 22:13:53 +08:00
|
|
|
|
if (e.GetCurrentPoint(this).Properties.IsLeftButtonPressed)
|
2026-04-10 12:20:05 +08:00
|
|
|
|
{
|
2026-04-10 22:13:53 +08:00
|
|
|
|
BeginMoveDrag(e);
|
2026-04-10 12:20:05 +08:00
|
|
|
|
}
|
|
|
|
|
|
}
|
2026-04-03 13:14:20 +08:00
|
|
|
|
|
|
|
|
|
|
protected override void OnClosed(EventArgs e)
|
|
|
|
|
|
{
|
|
|
|
|
|
base.OnClosed(e);
|
|
|
|
|
|
var mainWindow = (Application.Current?.ApplicationLifetime as IClassicDesktopStyleApplicationLifetime)?.MainWindow as MainWindow;
|
|
|
|
|
|
mainWindow?.UnregisterFusedLibraryWindow(this);
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
public void UpdatePreviewImage(ComponentPreviewImageEntry entry)
|
|
|
|
|
|
{
|
|
|
|
|
|
LibraryControl.UpdatePreviewImage(entry);
|
|
|
|
|
|
}
|
2026-04-02 21:12:06 +08:00
|
|
|
|
}
|