WaterTankControl.cs 3.6 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374
  1. using Avalonia;
  2. using Avalonia.Controls;
  3. using Avalonia.Media;
  4. using System;
  5. using System.Globalization;
  6. namespace YZWater.Avalonia.Controls;
  7. public class WaterTankControl : Control
  8. {
  9. public static readonly StyledProperty<double> WaterLevelProperty =
  10. AvaloniaProperty.Register<WaterTankControl, double>(nameof(WaterLevel), 50.0);
  11. public static readonly StyledProperty<string> TextProperty =
  12. AvaloniaProperty.Register<WaterTankControl, string>(nameof(Text), string.Empty);
  13. public static readonly StyledProperty<IBrush> WaterColorProperty =
  14. AvaloniaProperty.Register<WaterTankControl, IBrush>(nameof(WaterColor));
  15. public static readonly StyledProperty<IBrush> BorderColorProperty =
  16. AvaloniaProperty.Register<WaterTankControl, IBrush>(nameof(BorderColor));
  17. public double WaterLevel { get => GetValue(WaterLevelProperty); set => SetValue(WaterLevelProperty, value); }
  18. public string Text { get => GetValue(TextProperty); set => SetValue(TextProperty, value); }
  19. public IBrush WaterColor { get => GetValue(WaterColorProperty); set => SetValue(WaterColorProperty, value); }
  20. public IBrush BorderColor { get => GetValue(BorderColorProperty); set => SetValue(BorderColorProperty, value); }
  21. static WaterTankControl() { AffectsRender<WaterTankControl>(WaterLevelProperty, TextProperty, WaterColorProperty, BorderColorProperty); }
  22. protected override void OnAttachedToVisualTree(VisualTreeAttachmentEventArgs e)
  23. {
  24. base.OnAttachedToVisualTree(e);
  25. ThemeHelper.ThemeChanged += OnThemeChanged;
  26. }
  27. protected override void OnDetachedFromVisualTree(VisualTreeAttachmentEventArgs e)
  28. {
  29. ThemeHelper.ThemeChanged -= OnThemeChanged;
  30. base.OnDetachedFromVisualTree(e);
  31. }
  32. private void OnThemeChanged() => InvalidateVisual();
  33. private static readonly Typeface s_typeface = new("Microsoft YaHei", FontStyle.Normal, FontWeight.Bold);
  34. public override void Render(DrawingContext context)
  35. {
  36. base.Render(context);
  37. var bounds = new Rect(Bounds.Size);
  38. var edgeWidth = 3.0;
  39. context.DrawRectangle(ThemeHelper.PanelBg, null, bounds);
  40. var borderColor = BorderColor ?? ThemeHelper.Border;
  41. context.DrawRectangle(null, new Pen(borderColor, edgeWidth), bounds);
  42. var waterHeight = (bounds.Height - edgeWidth * 2) * Math.Max(0, Math.Min(100, WaterLevel)) / 100.0;
  43. if (waterHeight > 0)
  44. {
  45. var waterColor = WaterColor ?? ThemeHelper.Success;
  46. var waterBrush = waterColor is SolidColorBrush sc ? new SolidColorBrush(sc.Color, 0.8) : waterColor;
  47. context.DrawRectangle(waterBrush, null, new Rect(bounds.X + edgeWidth, bounds.Y + bounds.Height - edgeWidth - waterHeight, bounds.Width - edgeWidth * 2, waterHeight));
  48. }
  49. if (!string.IsNullOrEmpty(Text))
  50. {
  51. var t = new FormattedText(Text, CultureInfo.CurrentCulture, FlowDirection.LeftToRight, s_typeface, 12, ThemeHelper.TextPrimary);
  52. context.DrawText(t, new Point(bounds.X + (bounds.Width - t.Width) / 2, bounds.Y + edgeWidth + 5));
  53. }
  54. var lt = new FormattedText($"{WaterLevel:F1}%", CultureInfo.CurrentCulture, FlowDirection.LeftToRight, s_typeface, 14, ThemeHelper.TextPrimary);
  55. var bg = new Rect(bounds.X + (bounds.Width - lt.Width - 10) / 2, bounds.Y + bounds.Height - edgeWidth - lt.Height - 10, lt.Width + 10, lt.Height + 6);
  56. context.DrawRectangle(new SolidColorBrush(Colors.Black, 0.5), null, bg);
  57. context.DrawText(lt, new Point(bg.X + 5, bg.Y + 3));
  58. }
  59. protected override Size MeasureOverride(Size availableSize) => new Size(120, 160);
  60. }