| 1 | extern alias svgctrl; |
| 2 | using System.Globalization; |
| 3 | using Avalonia.Data.Converters; |
| 4 | using CascadeIDE.Features.UiChrome; |
| 5 | using CascadeIDE.Features.Workspace.Application; |
| 6 | using CascadeIDE.Models; |
| 7 | using SvgImage = svgctrl::Avalonia.Svg.SvgImage; |
| 8 | using SvgSource = svgctrl::Avalonia.Svg.SvgSource; |
| 9 | |
| 10 | namespace CascadeIDE.Views; |
| 11 | |
| 12 | /// <summary>Преобразует SolutionItem в иконку для дерева решения (ADR 0167 icon set).</summary> |
| 13 | public sealed class SolutionItemIconConverter : IMultiValueConverter |
| 14 | { |
| 15 | private const string AvaresBase = "avares://CascadeIDE/Assets/Icons/"; |
| 16 | private static readonly Dictionary<string, SvgSource> Cache = new(StringComparer.OrdinalIgnoreCase); |
| 17 | private static readonly object CacheLock = new(); |
| 18 | |
| 19 | private static SvgSource? LoadSvg(string assetName) |
| 20 | { |
| 21 | foreach (var candidate in FallbackAssetNames(assetName)) |
| 22 | { |
| 23 | var path = AvaresBase + candidate + ".svg"; |
| 24 | lock (CacheLock) |
| 25 | { |
| 26 | if (Cache.TryGetValue(candidate, out var cached)) |
| 27 | return cached; |
| 28 | } |
| 29 | |
| 30 | var source = SvgSource.Load(path, null); |
| 31 | if (source?.Picture is null) |
| 32 | continue; |
| 33 | |
| 34 | lock (CacheLock) |
| 35 | Cache[candidate] = source; |
| 36 | return source; |
| 37 | } |
| 38 | |
| 39 | return null; |
| 40 | } |
| 41 | |
| 42 | private static IEnumerable<string> FallbackAssetNames(string assetName) |
| 43 | { |
| 44 | yield return assetName; |
| 45 | if (string.Equals(assetName, "file", StringComparison.OrdinalIgnoreCase)) |
| 46 | yield return "cs"; |
| 47 | } |
| 48 | |
| 49 | public object? Convert(IList<object?> values, Type targetType, object? parameter, CultureInfo culture) |
| 50 | { |
| 51 | var key = values.Count > 0 && values[0] is SolutionItem item |
| 52 | ? item.IconKey |
| 53 | : values.FirstOrDefault()?.ToString(); |
| 54 | if (string.IsNullOrEmpty(key)) |
| 55 | key = "file"; |
| 56 | |
| 57 | var powerMonochrome = values.Count > 1 && values[1] is UiModeFamily family |
| 58 | ? family.IsPowerFamily() |
| 59 | : false; |
| 60 | |
| 61 | var assetName = SolutionExplorerIconKeys.ResolveAssetName(key, powerMonochrome); |
| 62 | var source = LoadSvg(assetName); |
| 63 | return source is null ? null : new SvgImage { Source = source }; |
| 64 | } |
| 65 | |
| 66 | public object? ConvertBack(IList<object?> values, Type targetType, object? parameter, CultureInfo culture) => |
| 67 | throw new NotImplementedException(); |
| 68 | } |
| 69 | |