211 lines
6.1 KiB
C#
211 lines
6.1 KiB
C#
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;
|
|
}
|
|
}
|
|
}
|