1
0
Fork 0

feat: Everything2Everything 양방향 변환 매트릭스 피보팅

EverythingToJpeg(N→JPEG 단방향)에서 Everything2Everything(N×M 매트릭스)으로
앱을 피보팅. 7개 Provider, 200+ 변환 쌍 지원.

리네이밍
- 디렉토리/솔루션/csproj/namespace/AssemblyName/MSIX Identity 일괄 치환
- 임시파일 prefix e2j_ → e2e_, 로고 라벨 E2J → E2E

아키텍처
- ConversionPair(input, output) 신규 + ProviderCapability.SupportedConversions
- IConverterProvider.ConvertAsync에 outputExtension 파라미터 추가
- ProviderRegistry를 Dictionary<(input, output), Provider> 매트릭스로 재작성
  + OutputsForInput / OutputsForFile 쿼리 API
- ConversionEngine: 출력 ext 라우팅, 동일 입출력 자동 skip,
  서브폴더 suffix를 출력 ext에서 자동 도출
- ConvertOptions를 형식별 sub-record로 분리
  (Jpeg/Png/Webp/Avif/Tiff/Pdf*/Html*/Ocr)

Provider 매트릭스
- MagickProvider: PNG/JPEG/WebP/AVIF/BMP/TIFF/GIF/PDF 양방향 + RAW/PSD 디코딩
  (단일이미지→1페이지 PDF, GIF/TIFF→다페이지 PDF)
- HeicProvider: HEIC/HEIF → 이미지 7종
- PdfProvider: PDF → 이미지 6종 (PNG임베드 후 ImageMagick 인코딩)
- HtmlProvider: HTML/HTM → 이미지 + PDF (CDP printToPDF)
- DocxProvider/HwpxProvider: PDF + 이미지 7종 (LibreOffice 활용)
- OcrProvider 신규: 이미지/PDF → TXT/DOCX
  (Windows.Media.Ocr + DocumentFormat.OpenXml, PDF는 페이지별 OCR 후 결합)

UI
- 사이드바 TARGET FORMAT을 동적 ComboBox로 (큐 파일 매트릭스의 교집합만 표시)
- 출력 형식별 색상 배지 + Quality 패널 라벨 동적
- OUTPUT DESTINATION hint도 출력 ext 기반 동적

CLI
- 신규 'to <ext> <files...>' verb (예: to png photo.heic doc.docx)
- help 텍스트 양방향 컨셉으로 갱신

셸 통합
- ContextMenuRegistrar 카스케이드로 재설계
  (ExtendedSubCommandsKey + Everything2Everything.SubMenu.<ext>)
- 입력별 매트릭스에 따라 인기 출력 10종(JPEG/PNG/WebP/PDF/TXT/DOCX/AVIF/GIF/TIFF/BMP)
  동적 노출, 마지막에 '변환…' 옵션
- 메뉴 라벨 'JPEG로 변환' → 'Everything2Everything으로 변환'

기타
- Core.csproj TFM net9.0-windows → net9.0-windows10.0.19041.0 (WinRT API용)
- DocumentFormat.OpenXml 3.1.0 NuGet 추가
- README 양방향 매트릭스 기준 전면 개편
- MSIX appxmanifest Description / IExplorerCommand DLL 라벨 갱신

빌드: 0 errors, 0 warnings
This commit is contained in:
Yun Chan 2026-05-07 13:40:08 +09:00
parent 96861e627d
commit 9b7e5f0d0c
63 changed files with 1788 additions and 733 deletions

View file

@ -1,293 +0,0 @@
<ResourceDictionary
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml">
<!-- Backgrounds -->
<SolidColorBrush x:Key="FsBgBase" Color="#090A0C"/>
<SolidColorBrush x:Key="FsBgPanel" Color="#131417"/>
<SolidColorBrush x:Key="FsBgSurface" Color="#1C1E22"/>
<SolidColorBrush x:Key="FsBgSurfaceHover" Color="#23252A"/>
<SolidColorBrush x:Key="FsBgInput" Color="#0F1012"/>
<!-- Borders -->
<SolidColorBrush x:Key="FsBorderSubtle" Color="#26282D"/>
<SolidColorBrush x:Key="FsBorderStrong" Color="#3A3D45"/>
<!-- Text -->
<SolidColorBrush x:Key="FsTextPrimary" Color="#ECEEFA"/>
<SolidColorBrush x:Key="FsTextSecondary" Color="#8B909A"/>
<SolidColorBrush x:Key="FsTextTertiary" Color="#5D626C"/>
<!-- Accents -->
<SolidColorBrush x:Key="FsAccentBlue" Color="#3B72FF"/>
<SolidColorBrush x:Key="FsAccentGreen" Color="#10B981"/>
<SolidColorBrush x:Key="FsAccentAmber" Color="#F59E0B"/>
<SolidColorBrush x:Key="FsAccentRed" Color="#EF4444"/>
<!-- Format pills -->
<SolidColorBrush x:Key="FsFmtPdf" Color="#E53E3E"/>
<SolidColorBrush x:Key="FsFmtPng" Color="#805AD5"/>
<SolidColorBrush x:Key="FsFmtHeic" Color="#D69E2E"/>
<SolidColorBrush x:Key="FsFmtJpg" Color="#3182CE"/>
<SolidColorBrush x:Key="FsFmtDocx" Color="#2B6CB0"/>
<SolidColorBrush x:Key="FsFmtHtml" Color="#DD6B20"/>
<SolidColorBrush x:Key="FsFmtRaw" Color="#319795"/>
<SolidColorBrush x:Key="FsFmtGif" Color="#9F7AEA"/>
<SolidColorBrush x:Key="FsFmtTiff" Color="#38B2AC"/>
<SolidColorBrush x:Key="FsFmtWebp" Color="#48BB78"/>
<SolidColorBrush x:Key="FsFmtBmp" Color="#718096"/>
<SolidColorBrush x:Key="FsFmtHwp" Color="#9B2C2C"/>
<SolidColorBrush x:Key="FsFmtOther" Color="#4A5568"/>
<!-- Font families -->
<FontFamily x:Key="FsFontSans">Inter, Segoe UI Variable Text, Segoe UI</FontFamily>
<FontFamily x:Key="FsFontMono">JetBrains Mono, Cascadia Mono, Consolas</FontFamily>
<!-- Typography styles -->
<Style x:Key="FsLabelStyle" TargetType="TextBlock">
<Setter Property="FontFamily" Value="{StaticResource FsFontSans}"/>
<Setter Property="FontSize" Value="11"/>
<Setter Property="FontWeight" Value="SemiBold"/>
<Setter Property="Foreground" Value="{StaticResource FsTextSecondary}"/>
<Setter Property="TextOptions.TextFormattingMode" Value="Display"/>
</Style>
<Style x:Key="FsCaptionStyle" TargetType="TextBlock">
<Setter Property="FontFamily" Value="{StaticResource FsFontSans}"/>
<Setter Property="FontSize" Value="11"/>
<Setter Property="Foreground" Value="{StaticResource FsTextTertiary}"/>
</Style>
<Style x:Key="FsBodyStyle" TargetType="TextBlock">
<Setter Property="FontFamily" Value="{StaticResource FsFontSans}"/>
<Setter Property="FontSize" Value="13"/>
<Setter Property="Foreground" Value="{StaticResource FsTextPrimary}"/>
</Style>
<Style x:Key="FsMonoStyle" TargetType="TextBlock">
<Setter Property="FontFamily" Value="{StaticResource FsFontMono}"/>
<Setter Property="FontSize" Value="12"/>
<Setter Property="Foreground" Value="{StaticResource FsTextSecondary}"/>
</Style>
<!-- Slider style: 2px track, 14px round thumb, blue fill up to value -->
<Style x:Key="FsSliderStyle" TargetType="Slider">
<Setter Property="Background" Value="Transparent"/>
<Setter Property="Foreground" Value="{StaticResource FsAccentBlue}"/>
<Setter Property="MinHeight" Value="20"/>
<Setter Property="VerticalAlignment" Value="Center"/>
<Setter Property="IsMoveToPointEnabled" Value="True"/>
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="Slider">
<Grid>
<Border Height="2" CornerRadius="1"
Background="{StaticResource FsBorderStrong}"
VerticalAlignment="Center"/>
<Track x:Name="PART_Track">
<Track.DecreaseRepeatButton>
<RepeatButton Command="Slider.DecreaseLarge">
<RepeatButton.Template>
<ControlTemplate TargetType="RepeatButton">
<Border Height="2" CornerRadius="1"
Background="{StaticResource FsAccentBlue}"
VerticalAlignment="Center"/>
</ControlTemplate>
</RepeatButton.Template>
</RepeatButton>
</Track.DecreaseRepeatButton>
<Track.Thumb>
<Thumb>
<Thumb.Template>
<ControlTemplate TargetType="Thumb">
<Ellipse Width="14" Height="14"
Fill="{StaticResource FsTextPrimary}"/>
</ControlTemplate>
</Thumb.Template>
</Thumb>
</Track.Thumb>
<Track.IncreaseRepeatButton>
<RepeatButton Command="Slider.IncreaseLarge">
<RepeatButton.Template>
<ControlTemplate TargetType="RepeatButton">
<Border Background="Transparent"/>
</ControlTemplate>
</RepeatButton.Template>
</RepeatButton>
</Track.IncreaseRepeatButton>
</Track>
</Grid>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
<!-- Tab pill style -->
<Style x:Key="FsTabPillStyle" TargetType="ToggleButton">
<Setter Property="Background" Value="Transparent"/>
<Setter Property="Foreground" Value="{StaticResource FsTextSecondary}"/>
<Setter Property="BorderThickness" Value="0"/>
<Setter Property="Padding" Value="14,6"/>
<Setter Property="FontSize" Value="13"/>
<Setter Property="FontWeight" Value="Medium"/>
<Setter Property="Cursor" Value="Hand"/>
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="ToggleButton">
<Border x:Name="PART_Bd" CornerRadius="20"
Padding="{TemplateBinding Padding}"
Background="{TemplateBinding Background}">
<ContentPresenter HorizontalAlignment="Center"
VerticalAlignment="Center"
TextElement.Foreground="{TemplateBinding Foreground}"/>
</Border>
<ControlTemplate.Triggers>
<Trigger Property="IsChecked" Value="True">
<Setter TargetName="PART_Bd" Property="Background" Value="{StaticResource FsAccentBlue}"/>
<Setter Property="Foreground" Value="White"/>
</Trigger>
<Trigger Property="IsMouseOver" Value="True">
<Setter TargetName="PART_Bd" Property="Background" Value="{StaticResource FsBgSurfaceHover}"/>
</Trigger>
<MultiTrigger>
<MultiTrigger.Conditions>
<Condition Property="IsChecked" Value="True"/>
<Condition Property="IsMouseOver" Value="True"/>
</MultiTrigger.Conditions>
<Setter TargetName="PART_Bd" Property="Background" Value="{StaticResource FsAccentBlue}"/>
</MultiTrigger>
</ControlTemplate.Triggers>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
<!-- Segment button style (Skip / Rename / Replace) -->
<Style x:Key="FsSegmentStyle" TargetType="ToggleButton">
<Setter Property="Background" Value="Transparent"/>
<Setter Property="Foreground" Value="{StaticResource FsTextSecondary}"/>
<Setter Property="BorderThickness" Value="0"/>
<Setter Property="FontSize" Value="12"/>
<Setter Property="FontWeight" Value="Medium"/>
<Setter Property="Cursor" Value="Hand"/>
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="ToggleButton">
<Border x:Name="PART_Bd" CornerRadius="4" Padding="0,6">
<ContentPresenter HorizontalAlignment="Center"
VerticalAlignment="Center"
TextElement.Foreground="{TemplateBinding Foreground}"/>
</Border>
<ControlTemplate.Triggers>
<Trigger Property="IsChecked" Value="True">
<Setter TargetName="PART_Bd" Property="Background" Value="{StaticResource FsBgSurface}"/>
<Setter Property="Foreground" Value="{StaticResource FsTextPrimary}"/>
</Trigger>
</ControlTemplate.Triggers>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
<!-- Primary button (Processing Queue / Run) -->
<Style x:Key="FsPrimaryButtonStyle" TargetType="Button">
<Setter Property="Background" Value="{StaticResource FsAccentBlue}"/>
<Setter Property="Foreground" Value="White"/>
<Setter Property="BorderThickness" Value="0"/>
<Setter Property="Padding" Value="12"/>
<Setter Property="FontSize" Value="13"/>
<Setter Property="FontWeight" Value="SemiBold"/>
<Setter Property="Cursor" Value="Hand"/>
<Setter Property="HorizontalContentAlignment" Value="Center"/>
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="Button">
<Border x:Name="PART_Bd"
Background="{TemplateBinding Background}"
CornerRadius="6"
Padding="{TemplateBinding Padding}">
<ContentPresenter HorizontalAlignment="Center" VerticalAlignment="Center"
TextElement.Foreground="{TemplateBinding Foreground}"
TextElement.FontSize="{TemplateBinding FontSize}"
TextElement.FontWeight="{TemplateBinding FontWeight}"/>
</Border>
<ControlTemplate.Triggers>
<Trigger Property="IsEnabled" Value="False">
<Setter TargetName="PART_Bd" Property="Opacity" Value="0.5"/>
<Setter Property="Cursor" Value="Arrow"/>
</Trigger>
<Trigger Property="IsMouseOver" Value="True">
<Setter TargetName="PART_Bd" Property="Background" Value="#2D5DDB"/>
</Trigger>
</ControlTemplate.Triggers>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
<!-- Secondary button -->
<Style x:Key="FsSecondaryButtonStyle" TargetType="Button">
<Setter Property="Background" Value="{StaticResource FsBgSurface}"/>
<Setter Property="Foreground" Value="{StaticResource FsTextPrimary}"/>
<Setter Property="BorderBrush" Value="{StaticResource FsBorderSubtle}"/>
<Setter Property="BorderThickness" Value="1"/>
<Setter Property="Padding" Value="12,6"/>
<Setter Property="FontSize" Value="12"/>
<Setter Property="FontWeight" Value="Medium"/>
<Setter Property="Cursor" Value="Hand"/>
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="Button">
<Border x:Name="PART_Bd"
Background="{TemplateBinding Background}"
BorderBrush="{TemplateBinding BorderBrush}"
BorderThickness="{TemplateBinding BorderThickness}"
CornerRadius="6"
Padding="{TemplateBinding Padding}">
<ContentPresenter HorizontalAlignment="Center" VerticalAlignment="Center"
TextElement.Foreground="{TemplateBinding Foreground}"
TextElement.FontSize="{TemplateBinding FontSize}"
TextElement.FontWeight="{TemplateBinding FontWeight}"/>
</Border>
<ControlTemplate.Triggers>
<Trigger Property="IsMouseOver" Value="True">
<Setter TargetName="PART_Bd" Property="Background" Value="{StaticResource FsBgSurfaceHover}"/>
</Trigger>
</ControlTemplate.Triggers>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
<!-- Tab badge -->
<Style x:Key="FsTabBadgeStyle" TargetType="Border">
<Setter Property="CornerRadius" Value="10"/>
<Setter Property="Padding" Value="6,1"/>
<Setter Property="Background" Value="{StaticResource FsBgSurface}"/>
</Style>
<!-- Path input box -->
<Style x:Key="FsPathInputStyle" TargetType="TextBox">
<Setter Property="Background" Value="{StaticResource FsBgInput}"/>
<Setter Property="Foreground" Value="{StaticResource FsTextSecondary}"/>
<Setter Property="BorderBrush" Value="{StaticResource FsBorderSubtle}"/>
<Setter Property="BorderThickness" Value="1"/>
<Setter Property="Padding" Value="10,8"/>
<Setter Property="FontFamily" Value="{StaticResource FsFontMono}"/>
<Setter Property="FontSize" Value="11"/>
<Setter Property="CaretBrush" Value="{StaticResource FsTextPrimary}"/>
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="TextBox">
<Border Background="{TemplateBinding Background}"
BorderBrush="{TemplateBinding BorderBrush}"
BorderThickness="{TemplateBinding BorderThickness}"
CornerRadius="6"
Padding="{TemplateBinding Padding}">
<ScrollViewer x:Name="PART_ContentHost"/>
</Border>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
</ResourceDictionary>