1
0
Fork 0

feat(ui): 출력 드롭다운에 형식 색 dot + 손실 등급 dot

변환 전에 '무엇으로 / 얼마나 보존되나'를 한눈에. 드롭다운 각 항목을 형식색 dot(8px) + 라벨 + 손실 등급 dot(6px, 큐 입력 기준 worst-case)로 렌더링.

- 형식색: FormatPalette.For 색 (csv 틸·json 골드·svg 핑크·영상 코랄·오디오 퍼플)
- 손실 dot: Lossless 초록 / Container 회색 / Recode 앰버 / Rasterize 빨강 (hover 툴팁)
- 손실 계산: ConversionGraph.FindBestPath worst Loss
This commit is contained in:
Yun Chan 2026-06-01 15:11:36 +09:00
parent 2a3d220db4
commit 5c7a4a9ee3

View file

@ -10,6 +10,7 @@ using System.Windows.Media;
using System.Windows.Media.Imaging; using System.Windows.Media.Imaging;
using Everything2Everything.App.Shell; using Everything2Everything.App.Shell;
using Everything2Everything.Core; using Everything2Everything.Core;
using LossClass = Everything2Everything.Core.Providers.LossClass;
namespace Everything2Everything.App.Views; namespace Everything2Everything.App.Views;
@ -857,6 +858,78 @@ public partial class MainWindow : Wpf.Ui.Controls.FluentWindow
RefreshAvailableOutputFormats(); RefreshAvailableOutputFormats();
} }
// 드롭다운 항목: 형식 색 dot + 라벨 + 손실 등급 dot (변환 전에 색·손실을 한눈에)
private object BuildFormatItemContent(OutputFormatInfo f)
{
var panel = new StackPanel { Orientation = Orientation.Horizontal, VerticalAlignment = VerticalAlignment.Center };
panel.Children.Add(new System.Windows.Shapes.Ellipse
{
Width = 8,
Height = 8,
VerticalAlignment = VerticalAlignment.Center,
Margin = new Thickness(0, 0, 9, 0),
Fill = ResBrush(f.ColorResource),
});
panel.Children.Add(new TextBlock
{
Text = $"{f.DisplayName} ({f.Extension})",
VerticalAlignment = VerticalAlignment.Center,
});
var loss = WorstLossForQueue(f.Extension);
if (loss is LossClass lc)
{
panel.Children.Add(new System.Windows.Shapes.Ellipse
{
Width = 6,
Height = 6,
VerticalAlignment = VerticalAlignment.Center,
Margin = new Thickness(8, 1, 0, 0),
Fill = ResBrush(LossDotKey(lc)),
ToolTip = LossLabel(lc),
});
}
return panel;
}
private LossClass? WorstLossForQueue(string outputExt)
{
if (_activeQueue.Count == 0) return null;
var graph = ((App)Application.Current).Engine.Providers.Graph;
LossClass? worst = null;
foreach (var item in _activeQueue)
{
var inExt = Path.GetExtension(item.SourcePath);
var path = graph.FindBestPath(inExt, outputExt, 3);
if (path is null || path.Count == 0) continue;
var pw = path.Max(e => e.Loss);
if (worst is null || pw > worst.Value) worst = pw;
}
return worst;
}
private static Brush ResBrush(string key) => (Brush)Application.Current.Resources[key];
private static string LossDotKey(LossClass lc) => lc switch
{
LossClass.Lossless => "FsLossLosslessDot",
LossClass.Container => "FsLossContainerDot",
LossClass.Recode => "FsLossRecodeDot",
LossClass.Rasterize => "FsLossRasterizeDot",
_ => "FsLossContainerDot",
};
private static string LossLabel(LossClass lc) => lc switch
{
LossClass.Lossless => "무손실 — 픽셀·내용 보존",
LossClass.Container => "구조 변경 — 내용 보존",
LossClass.Recode => "재인코딩 — 약간의 품질 손실",
LossClass.Rasterize => "래스터화 — 편집성 상실 (단방향)",
_ => "",
};
private void RefreshAvailableOutputFormats() private void RefreshAvailableOutputFormats()
{ {
if (OutputFormatCombo is null) return; if (OutputFormatCombo is null) return;
@ -897,7 +970,7 @@ public partial class MainWindow : Wpf.Ui.Controls.FluentWindow
{ {
OutputFormatCombo.Items.Add(new ComboBoxItem OutputFormatCombo.Items.Add(new ComboBoxItem
{ {
Content = $"{f.DisplayName} ({f.Extension})", Content = BuildFormatItemContent(f),
Tag = f.Extension, Tag = f.Extension,
}); });
} }