using System.Globalization; using System.Windows.Data; using System.Windows.Media; namespace SheetMe.Designer.Controls; /// /// 팔레트 타입 → (Lucide 아이콘, 카테고리) 매핑 — [200]SheetMe 팔레트 타일 룩 이식. /// Core(ControlRegistry)는 UI 무관하게 유지하고 표시 계층인 여기서만 매핑한다. /// public static class PaletteIconCatalog { #region Member Fields private static readonly Dictionary Map = new(StringComparer.Ordinal) { ["Label"] = ("type", "표시"), ["PictureBox"] = ("image", "표시"), ["Line"] = ("minus", "표시"), // MaskedTextBox 는 TextBox 와 아이콘이 겹쳐 구분이 안 됐다 — [200] 어휘로 분리 ["TextBox"] = ("text-cursor-input", "입력"), ["MaskedTextBox"] = ("type", "입력"), ["ComboBox"] = ("list", "입력"), ["ListBox"] = ("list-checks", "입력"), ["CheckList"] = ("list-checks", "입력"), ["DateTimePicker"] = ("calendar", "입력"), ["CalcBox"] = ("sigma", "입력"), ["CheckBox"] = ("square-check", "선택"), ["RadioButton"] = ("circle-dot", "선택"), ["Panel"] = ("package", "컨테이너"), ["GroupBox"] = ("box", "컨테이너"), ["Button"] = ("mouse-pointer-click", "동작/데이터"), ["DataTable"] = ("table", "동작/데이터"), }; #endregion #region Methods /// 타입의 Lucide 아이콘명(미지정 타입은 square) public static string IconOf(string type) => Map.TryGetValue(type, out var entry) ? entry.Icon : "square"; /// 타입의 팔레트 카테고리(그룹 헤더) public static string CategoryOf(string type) => Map.TryGetValue(type, out var entry) ? entry.Category : "기타"; #endregion } /// /// 아이콘 컨버터 공용 파라미터 해석 — "크기" 또는 "크기|브러시키". /// /// 브러시 키를 생략하면 종전처럼 B.Muted 를 쓴다(하위호환). 색을 인자로 받을 수 있어야 /// 활성 문서 탭 아이콘을 강조색으로, 레이어 타입 아이콘을 본문색으로 굽는 것이 가능해진다. /// internal static class IconParam { public static (double Size, Brush Brush) Parse(object? parameter, double defaultSize) { var size = defaultSize; var key = "B.Muted"; if (parameter is string text && text.Length > 0) { var bar = text.IndexOf('|'); var sizePart = bar >= 0 ? text[..bar] : text; if (bar >= 0 && bar + 1 < text.Length) { key = text[(bar + 1)..].Trim(); } if (double.TryParse(sizePart, NumberStyles.Float, CultureInfo.InvariantCulture, out var parsed)) { size = parsed; } } var brush = System.Windows.Application.Current?.TryFindResource(key) as Brush ?? Brushes.Gray; return (size, brush); } } /// 팔레트 타입명 → Lucide 아이콘 비주얼(FrameworkElement) 컨버터. parameter="크기" 또는 "크기|브러시키"(기본 18, B.Muted) public sealed class TypeToIconConverter : IValueConverter { public object? Convert(object? value, Type targetType, object? parameter, CultureInfo culture) { if (value is not string type) { return null; } var (size, brush) = IconParam.Parse(parameter, 18); return LucideIcons.Icon(PaletteIconCatalog.IconOf(type), size, brush); } public object ConvertBack(object? value, Type targetType, object? parameter, CultureInfo culture) => throw new NotSupportedException(); } /// 팔레트 타입명 → 카테고리명 컨버터(CollectionViewSource 그룹핑용) public sealed class TypeToCategoryConverter : IValueConverter { public object Convert(object? value, Type targetType, object? parameter, CultureInfo culture) => value is string type ? PaletteIconCatalog.CategoryOf(type) : "기타"; public object ConvertBack(object? value, Type targetType, object? parameter, CultureInfo culture) => throw new NotSupportedException(); } /// 불리언 반전 컨버터(선택 도구 토글 = !IsHandTool 표시용) public sealed class InverseBoolConverter : IValueConverter { public object Convert(object? value, Type targetType, object? parameter, CultureInfo culture) => value is not true; public object ConvertBack(object? value, Type targetType, object? parameter, CultureInfo culture) => value is not true; } /// /// Lucide 아이콘명 → 비주얼 컨버터(문서 탭 file-text, 플로팅 바 layout-grid 등 고정 아이콘용). /// Binding Source 에 아이콘명 문자열을 넣어 사용 — 항목마다 새 비주얼이 생성되어 공유 부모 충돌이 없다. /// parameter="크기" 또는 "크기|브러시키"(기본 14, B.Muted). /// public sealed class IconNameToVisualConverter : IValueConverter { public object? Convert(object? value, Type targetType, object? parameter, CultureInfo culture) { if (value is not string name) { return null; } var (size, brush) = IconParam.Parse(parameter, 14); return LucideIcons.Icon(name, size, brush); } public object ConvertBack(object? value, Type targetType, object? parameter, CultureInfo culture) => throw new NotSupportedException(); }