This commit is contained in:
Meik
2025-11-11 11:03:42 +01:00
commit dc3e8a2e4c
582 changed files with 191465 additions and 0 deletions

View File

@@ -0,0 +1,210 @@
using C4IT.Graphics;
using System;
using System.Collections.Generic;
using System.Drawing;
using System.Drawing.Drawing2D;
using System.Linq;
using System.Windows.Forms;
using static C4IT.Logging.cLogManager;
namespace FasdDesktopUi.Basics.Helper
{
internal sealed class TrayTicketNotificationManager
{
private readonly NotifyIcon _notifyIcon;
private readonly object _syncRoot = new object();
private string _baseTooltip;
private string _currentTooltip;
private bool _overlayInitialized;
private const string OverlayKey = "TicketChanges";
private const string OverlaySetName = "OverlayTicketChanges";
public TrayTicketNotificationManager(NotifyIcon notifyIcon)
{
_notifyIcon = notifyIcon ?? throw new ArgumentNullException(nameof(notifyIcon));
}
public bool HasNotification
{
get
{
lock (_syncRoot)
return !string.IsNullOrWhiteSpace(_currentTooltip);
}
}
public void CaptureBaseTooltip()
{
lock (_syncRoot)
{
_baseTooltip = _notifyIcon.Text;
}
}
public void Show(string message)
{
if (string.IsNullOrWhiteSpace(message))
{
Clear();
return;
}
EnsureOverlaySet();
lock (_syncRoot)
{
_currentTooltip = BuildTooltip(message);
}
NotifyerSupport.SetNotifyIconOverlay(OverlayKey, OverlaySetName, NotifyerSupport.enumIconAlignment.TopRight, priority: 100);
ApplyTooltip();
}
public void Clear()
{
lock (_syncRoot)
{
_currentTooltip = null;
}
NotifyerSupport.SetNotifyIconOverlay(OverlayKey, null, NotifyerSupport.enumIconAlignment.TopRight);
ApplyTooltip();
}
public void ApplyTooltip()
{
if (_notifyIcon == null)
return;
string tooltip;
lock (_syncRoot)
{
tooltip = string.IsNullOrWhiteSpace(_currentTooltip)
? _baseTooltip
: $"F4SD - {_currentTooltip}";
}
_notifyIcon.Text = TrimTooltip(tooltip);
}
private void EnsureOverlaySet()
{
if (_overlayInitialized)
return;
try
{
var overlayFactories = new Dictionary<int, Func<Bitmap>>();
var sizeMap = new SortedDictionary<int, int>();
foreach (var size in NotifyerSupport.DefaultIconSizes)
{
var overlaySize = CalculateOverlayDiameter(size);
if (overlaySize <= 0)
continue;
sizeMap[size] = overlaySize;
if (!overlayFactories.ContainsKey(overlaySize))
{
var localSize = overlaySize;
overlayFactories[localSize] = () => CreateBadgeBitmap(localSize);
}
}
var iconSet = NotifyerSupport.RegisterDynamicSet(OverlaySetName, overlayFactories, NoRefresh: true)
?? NotifyerSupport.GetIconSet(OverlaySetName);
if (iconSet != null)
{
iconSet.SizeMap = sizeMap;
_overlayInitialized = true;
}
}
catch (Exception ex)
{
LogException(ex);
}
}
private static string BuildTooltip(string message)
{
try
{
var parts = message
.Split(new[] { '\r', '\n' }, StringSplitOptions.RemoveEmptyEntries)
.Select(part => part.Trim())
.Where(part => part.Length > 0);
var summary = string.Join(" | ", parts);
if (summary.Length > 140)
summary = summary.Substring(0, 139) + "…";
return summary;
}
catch
{
return message;
}
}
private static string TrimTooltip(string tooltip)
{
if (string.IsNullOrWhiteSpace(tooltip))
return tooltip;
tooltip = tooltip.Replace("\r", " ").Replace("\n", " ");
tooltip = tooltip.Trim();
return tooltip.Length <= 63
? tooltip
: tooltip.Substring(0, 63);
}
private static int CalculateOverlayDiameter(int baseSize)
{
if (baseSize <= 0)
return 0;
if (baseSize <= 18)
return 8;
if (baseSize <= 26)
return 10;
if (baseSize <= 36)
return 11;
var diameter = (int)Math.Round(baseSize * 0.22f);
return Math.Max(9, Math.Min(diameter, baseSize));
}
private static Bitmap CreateBadgeBitmap(int size)
{
var diameter = Math.Max(2, size);
var bitmap = new Bitmap(diameter, diameter, System.Drawing.Imaging.PixelFormat.Format32bppArgb);
bitmap.SetResolution(96f, 96f);
using (var graphics = Graphics.FromImage(bitmap))
{
graphics.SmoothingMode = SmoothingMode.AntiAlias;
graphics.Clear(Color.Transparent);
int margin = 0;
if (diameter >= 12)
margin = Math.Max(1, (int)Math.Round(diameter * 0.08f));
else if (diameter >= 9)
margin = 1;
var circleSize = Math.Max(1, diameter - (margin * 2));
var circleRect = new Rectangle(margin, margin, circleSize, circleSize);
using (var brush = new SolidBrush(Color.FromArgb(235, 220, 0, 0)))
{
graphics.FillEllipse(brush, circleRect);
}
}
return bitmap;
}
}
}