mirror of
https://github.com/wwiinnddyy/LanMountainDesktop.git
synced 2026-06-20 23:54:26 +08:00
228 lines
7.9 KiB
C#
228 lines
7.9 KiB
C#
using Avalonia;
|
|
using Avalonia.Controls;
|
|
using Avalonia.Layout;
|
|
using Avalonia.Media;
|
|
using Avalonia.Threading;
|
|
using LanMountainDesktop.PluginSdk;
|
|
|
|
namespace LanMountainDesktop.SamplePlugin;
|
|
|
|
internal sealed class SamplePluginStatusClockWidget : Border
|
|
{
|
|
private readonly DispatcherTimer _timer = new()
|
|
{
|
|
Interval = TimeSpan.FromSeconds(1)
|
|
};
|
|
|
|
private readonly PluginDesktopComponentContext _context;
|
|
private readonly TextBlock _timeTextBlock;
|
|
private readonly TextBlock _titleTextBlock;
|
|
private readonly StackPanel _statusPanel;
|
|
|
|
public SamplePluginStatusClockWidget(PluginDesktopComponentContext context)
|
|
{
|
|
_context = context;
|
|
_timeTextBlock = new TextBlock
|
|
{
|
|
Foreground = Brushes.White,
|
|
FontWeight = FontWeight.Bold,
|
|
HorizontalAlignment = HorizontalAlignment.Left
|
|
};
|
|
_titleTextBlock = new TextBlock
|
|
{
|
|
Text = "Plugin Status",
|
|
Foreground = new SolidColorBrush(Color.Parse("#FFBFE9FF")),
|
|
HorizontalAlignment = HorizontalAlignment.Left
|
|
};
|
|
_statusPanel = new StackPanel
|
|
{
|
|
Spacing = 8
|
|
};
|
|
|
|
Background = new LinearGradientBrush
|
|
{
|
|
StartPoint = new RelativePoint(0, 0, RelativeUnit.Relative),
|
|
EndPoint = new RelativePoint(1, 1, RelativeUnit.Relative),
|
|
GradientStops =
|
|
[
|
|
new GradientStop(Color.Parse("#FF07111F"), 0),
|
|
new GradientStop(Color.Parse("#FF0C4A6E"), 0.55),
|
|
new GradientStop(Color.Parse("#FF0EA5E9"), 1)
|
|
]
|
|
};
|
|
BorderBrush = new SolidColorBrush(Color.Parse("#6648C7FF"));
|
|
BorderThickness = new Thickness(1);
|
|
HorizontalAlignment = HorizontalAlignment.Stretch;
|
|
VerticalAlignment = VerticalAlignment.Stretch;
|
|
Child = new Grid
|
|
{
|
|
RowDefinitions = new RowDefinitions("Auto,*"),
|
|
RowSpacing = 14,
|
|
Children =
|
|
{
|
|
new StackPanel
|
|
{
|
|
Spacing = 4,
|
|
HorizontalAlignment = HorizontalAlignment.Left,
|
|
Children =
|
|
{
|
|
_timeTextBlock,
|
|
_titleTextBlock
|
|
}
|
|
},
|
|
new Border
|
|
{
|
|
Background = new SolidColorBrush(Color.Parse("#1F082F49")),
|
|
BorderBrush = new SolidColorBrush(Color.Parse("#5538BDF8")),
|
|
BorderThickness = new Thickness(1),
|
|
CornerRadius = new CornerRadius(18),
|
|
Padding = new Thickness(12),
|
|
Child = _statusPanel
|
|
}
|
|
}
|
|
};
|
|
|
|
Grid.SetRow(((Grid)Child).Children[1], 1);
|
|
|
|
_timer.Tick += OnTimerTick;
|
|
AttachedToVisualTree += OnAttachedToVisualTree;
|
|
DetachedFromVisualTree += OnDetachedFromVisualTree;
|
|
SizeChanged += OnSizeChanged;
|
|
|
|
var placementText = string.IsNullOrWhiteSpace(context.PlacementId)
|
|
? "Preview instance created."
|
|
: $"Widget created for placement {context.PlacementId}.";
|
|
SamplePluginRuntimeStatus.MarkFrontendReady("Widget frontend surface rendered successfully.");
|
|
SamplePluginRuntimeStatus.MarkComponentCreated($"{placementText} Baseline footprint: 4x4.");
|
|
|
|
RefreshClock();
|
|
RefreshStatusPanel();
|
|
ApplyScale();
|
|
}
|
|
|
|
private void OnAttachedToVisualTree(object? sender, VisualTreeAttachmentEventArgs e)
|
|
{
|
|
RefreshClock();
|
|
RefreshStatusPanel();
|
|
_timer.Start();
|
|
}
|
|
|
|
private void OnDetachedFromVisualTree(object? sender, VisualTreeAttachmentEventArgs e)
|
|
{
|
|
_timer.Stop();
|
|
}
|
|
|
|
private void OnTimerTick(object? sender, EventArgs e)
|
|
{
|
|
RefreshClock();
|
|
RefreshStatusPanel();
|
|
}
|
|
|
|
private void OnSizeChanged(object? sender, SizeChangedEventArgs e)
|
|
{
|
|
ApplyScale();
|
|
RefreshStatusPanel();
|
|
}
|
|
|
|
private void RefreshClock()
|
|
{
|
|
_timeTextBlock.Text = DateTime.Now.ToString("HH:mm:ss");
|
|
}
|
|
|
|
private void RefreshStatusPanel()
|
|
{
|
|
_statusPanel.Children.Clear();
|
|
|
|
var basis = GetLayoutBasis();
|
|
var titleSize = Math.Clamp(basis * 0.072, 11, 16);
|
|
var detailSize = Math.Clamp(basis * 0.055, 10, 13);
|
|
|
|
foreach (var entry in SamplePluginRuntimeStatus.GetSnapshot())
|
|
{
|
|
var palette = GetPalette(entry.State);
|
|
var summaryText = $"{entry.Summary} - {entry.UpdatedAt.LocalDateTime:HH:mm:ss}";
|
|
|
|
_statusPanel.Children.Add(new Border
|
|
{
|
|
Background = new SolidColorBrush(palette.Background),
|
|
BorderBrush = new SolidColorBrush(palette.Border),
|
|
BorderThickness = new Thickness(1),
|
|
CornerRadius = new CornerRadius(12),
|
|
Padding = new Thickness(10, 8),
|
|
Child = new Grid
|
|
{
|
|
ColumnDefinitions = new ColumnDefinitions("Auto,*,Auto"),
|
|
ColumnSpacing = 8,
|
|
Children =
|
|
{
|
|
new Border
|
|
{
|
|
Width = Math.Clamp(basis * 0.038, 8, 11),
|
|
Height = Math.Clamp(basis * 0.038, 8, 11),
|
|
CornerRadius = new CornerRadius(999),
|
|
Background = new SolidColorBrush(palette.Dot),
|
|
VerticalAlignment = VerticalAlignment.Center
|
|
},
|
|
new TextBlock
|
|
{
|
|
Text = entry.Title,
|
|
FontSize = titleSize,
|
|
FontWeight = FontWeight.SemiBold,
|
|
Foreground = Brushes.White,
|
|
TextWrapping = TextWrapping.Wrap
|
|
},
|
|
new TextBlock
|
|
{
|
|
Text = summaryText,
|
|
FontSize = detailSize,
|
|
Foreground = new SolidColorBrush(Color.Parse("#FFD7F2FF")),
|
|
HorizontalAlignment = HorizontalAlignment.Right,
|
|
TextAlignment = TextAlignment.Right,
|
|
VerticalAlignment = VerticalAlignment.Center
|
|
}
|
|
}
|
|
}
|
|
});
|
|
|
|
var row = (Grid)((Border)_statusPanel.Children[^1]).Child!;
|
|
Grid.SetColumn(row.Children[1], 1);
|
|
Grid.SetColumn(row.Children[2], 2);
|
|
}
|
|
}
|
|
|
|
private void ApplyScale()
|
|
{
|
|
var basis = GetLayoutBasis();
|
|
Padding = new Thickness(Math.Clamp(basis * 0.09, 16, 26));
|
|
CornerRadius = new CornerRadius(Math.Clamp(basis * 0.14, 20, 34));
|
|
_timeTextBlock.FontSize = Math.Clamp(basis * 0.22, 30, 58);
|
|
_titleTextBlock.FontSize = Math.Clamp(basis * 0.07, 12, 18);
|
|
}
|
|
|
|
private double GetLayoutBasis()
|
|
{
|
|
var width = Bounds.Width > 1 ? Bounds.Width : _context.CellSize * 4;
|
|
var height = Bounds.Height > 1 ? Bounds.Height : _context.CellSize * 4;
|
|
return Math.Max(_context.CellSize * 4, Math.Min(width, height));
|
|
}
|
|
|
|
private static (Color Background, Color Border, Color Dot) GetPalette(SamplePluginHealthState state)
|
|
{
|
|
return state switch
|
|
{
|
|
SamplePluginHealthState.Healthy => (
|
|
Color.Parse("#1F0F766E"),
|
|
Color.Parse("#4D5EEAD4"),
|
|
Color.Parse("#5EEAD4")),
|
|
SamplePluginHealthState.Faulted => (
|
|
Color.Parse("#29B91C1C"),
|
|
Color.Parse("#66F87171"),
|
|
Color.Parse("#F87171")),
|
|
_ => (
|
|
Color.Parse("#1F7C2D12"),
|
|
Color.Parse("#66FDBA74"),
|
|
Color.Parse("#FDBA74"))
|
|
};
|
|
}
|
|
}
|