Files
AX-Copilot-Codex/src/AxCopilot/Themes/Converters.cs
lacvet fb0bea41f7 AX Agent 코워크·코드 흐름과 컨텍스트 관리를 claude-code 기준으로 대폭 정리
- 코워크·코드 프롬프트, 도구 선택, 문서 생성/검증 흐름을 claude-code 동등 품질 기준으로 재정렬함

- OpenAI/vLLM 경로의 오래된 tool history를 평탄화하고 최근 이력만 구조화해 컨텍스트 직렬화를 경량화함

- AX Agent UI를 테마 기준으로 재구성하고 플랜 승인/오버레이/이벤트 렌더링/명령 입력 상호작용을 개선함

- 파일 후보 제안, 반복 경로 정체 복구, LSP 보강, 문서·PPT 처리 개선, 설정/서비스 인터페이스 정리를 함께 반영함

- README.md 및 docs/DEVELOPMENT.md를 작업 시점별로 갱신함

- 검증: dotnet build src/AxCopilot/AxCopilot.csproj -c Release -v minimal -p:OutputPath=bin\\verify\\ -p:IntermediateOutputPath=obj\\verify\\ (경고 0, 오류 0)
2026-04-12 22:02:14 +09:00

191 lines
7.8 KiB
C#

using System.Globalization;
using System.Windows;
using System.Windows.Data;
using System.Windows.Media;
namespace AxCopilot.Themes;
public class BoolToVisibilityConverter : IValueConverter
{
public object Convert(object value, Type t, object p, CultureInfo c) =>
value is true ? Visibility.Visible : Visibility.Collapsed;
public object ConvertBack(object v, Type t, object p, CultureInfo c) =>
v is Visibility.Visible;
}
public class InverseBoolToVisibilityConverter : IValueConverter
{
public object Convert(object value, Type t, object p, CultureInfo c) =>
value is true ? Visibility.Collapsed : Visibility.Visible;
public object ConvertBack(object v, Type t, object p, CultureInfo c) =>
v is not Visibility.Visible;
}
public class CountToVisibilityConverter : IValueConverter
{
public object Convert(object value, Type t, object p, CultureInfo c) =>
value is int count && count > 0 ? Visibility.Visible : Visibility.Collapsed;
public object ConvertBack(object v, Type t, object p, CultureInfo c) =>
throw new NotImplementedException();
}
/// <summary>
/// Segoe MDL2 심볼 코드포인트 → 아이콘 배경 SolidColorBrush.
/// 핸들러 타입별로 서로 다른 색상을 반환합니다.
/// </summary>
public class SymbolToBackgroundConverter : IValueConverter
{
private static readonly Dictionary<string, SolidColorBrush> SymbolColors = new()
{
{ Symbols.Globe, Brush("#0078D4") }, // URL — Microsoft Blue
{ Symbols.Folder, Brush("#107C10") }, // 폴더 — Green
{ Symbols.Terminal, Brush("#1B1B1B") }, // 터미널 — Near Black
{ Symbols.Clipboard, Brush("#8764B8") }, // 클립보드 — Purple
{ Symbols.Workspace, Brush("#C50F1F") }, // 워크스페이스 — Red
{ Symbols.Cloud, Brush("#0099BC") }, // API — Teal
{ Symbols.Plugin, Brush("#C239B3") }, // 플러그인 — Magenta
{ Symbols.App, Brush("#4B5EFC") }, // 앱 — Accent
{ Symbols.File, Brush("#605E5C") }, // 파일 — Gray
{ Symbols.Save, Brush("#107C10") }, // 저장 — Green
{ Symbols.Delete, Brush("#C50F1F") }, // 삭제 — Red
{ Symbols.Rename, Brush("#CA5010") }, // 이름변경 — Orange
{ Symbols.Restore, Brush("#0078D4") }, // 복원 — Blue
{ Symbols.Info, Brush("#4B5EFC") }, // 정보 — Accent
{ Symbols.Warning, Brush("#CA5010") }, // 경고 — Orange
{ Symbols.Error, Brush("#C50F1F") }, // 오류 — Red
};
private static readonly SolidColorBrush DefaultBrush = Brush("#4B5EFC");
public object Convert(object value, Type t, object p, CultureInfo c) =>
value is string symbol && SymbolColors.TryGetValue(symbol, out var brush)
? brush : DefaultBrush;
public object ConvertBack(object v, Type t, object p, CultureInfo c) =>
throw new NotImplementedException();
private static SolidColorBrush Brush(string hex)
{
var color = (Color)ColorConverter.ConvertFromString(hex);
var brush = new SolidColorBrush(color);
brush.Freeze();
return brush;
}
}
/// <summary>
/// 바인딩 값과 파라미터 문자열이 일치하는지 여부를 bool로 반환합니다.
/// RadioButton IsChecked 바인딩에 사용합니다.
/// </summary>
public class StringEqualConverter : IValueConverter
{
public object Convert(object value, Type t, object p, CultureInfo c) =>
value is string s && p is string param && s == param;
public object ConvertBack(object v, Type t, object p, CultureInfo c) =>
v is true ? p : System.Windows.Data.Binding.DoNothing;
}
/// <summary>
/// "#RRGGBB" 헥스 문자열 → WPF Color 변환기 (테마 카드 미리보기용).
/// XAML에서 {x:Static converters:HexToColorConverter.Instance} 로 사용합니다.
/// </summary>
public class HexToColorConverter : IValueConverter
{
public static readonly HexToColorConverter Instance = new();
public object Convert(object value, Type t, object p, CultureInfo c)
{
if (value is string hex)
{
try { return (Color)ColorConverter.ConvertFromString(hex); }
catch { /* 잘못된 값이면 기본 반환 */ }
}
return Colors.Transparent;
}
public object ConvertBack(object v, Type t, object p, CultureInfo c) =>
throw new NotImplementedException();
}
/// <summary>"#RRGGBB" 헥스 문자열 → SolidColorBrush. DataTemplate 아이콘 색상에 사용.</summary>
public class HexToBrushConverter : IValueConverter
{
public object Convert(object value, Type t, object p, CultureInfo c)
{
if (value is string hex && !string.IsNullOrEmpty(hex))
{
try
{
var color = (Color)ColorConverter.ConvertFromString(hex);
var brush = new SolidColorBrush(color);
brush.Freeze();
return brush;
}
catch { /* 잘못된 값이면 기본 반환 */ }
}
return new SolidColorBrush(Color.FromRgb(0x6B, 0x72, 0x80));
}
public object ConvertBack(object v, Type t, object p, CultureInfo c) =>
throw new NotImplementedException();
}
/// <summary>null 또는 빈 문자열이면 Collapsed, 값이 있으면 Visible.</summary>
public class NullToCollapsedConverter : IValueConverter
{
public object Convert(object value, Type t, object p, CultureInfo c) =>
value is string s && !string.IsNullOrEmpty(s) ? Visibility.Visible : Visibility.Collapsed;
public object ConvertBack(object v, Type t, object p, CultureInfo c) =>
throw new NotImplementedException();
}
/// <summary>LauncherItem.Data가 ClipboardEntry(이미지)면 썸네일 BitmapSource 반환.</summary>
public class ClipboardThumbnailConverter : IValueConverter
{
public object? Convert(object value, Type t, object p, CultureInfo c)
{
if (value is Services.ClipboardEntry { Image: not null } entry)
return entry.Image;
return null;
}
public object ConvertBack(object v, Type t, object p, CultureInfo c) =>
throw new NotImplementedException();
}
/// <summary>ClipboardEntry 이미지가 있으면 Visible.</summary>
public class ClipboardHasImageConverter : IValueConverter
{
public object Convert(object value, Type t, object p, CultureInfo c) =>
value is Services.ClipboardEntry { Image: not null } ? Visibility.Visible : Visibility.Collapsed;
public object ConvertBack(object v, Type t, object p, CultureInfo c) =>
throw new NotImplementedException();
}
/// <summary>Subtitle에 경고 기호(⚠)가 포함되면 Visible, 아니면 Collapsed 반환.</summary>
public class WarningSubtitleColorConverter : IValueConverter
{
public object Convert(object value, Type t, object p, CultureInfo c) =>
value is string s && s.Contains('\u26A0') ? Visibility.Visible : Visibility.Collapsed;
public object ConvertBack(object v, Type t, object p, CultureInfo c) =>
throw new NotImplementedException();
}
/// <summary>ListViewItem → 1-based 인덱스 문자열. 9 초과 시 빈 문자열.</summary>
public class IndexToNumberConverter : IValueConverter
{
public object Convert(object value, Type t, object p, CultureInfo c)
{
if (value is System.Windows.Controls.ListViewItem item)
{
var lv = System.Windows.Controls.ItemsControl.ItemsControlFromItemContainer(item);
if (lv != null)
{
var idx = lv.ItemContainerGenerator.IndexFromContainer(item);
return idx >= 0 && idx < 9 ? (idx + 1).ToString() : "";
}
}
return "";
}
public object ConvertBack(object v, Type t, object p, CultureInfo c) =>
throw new NotImplementedException();
}