[Phase52] PreviewWindow.xaml.cs 분리 — Content.cs 추출

- PreviewWindow.xaml.cs: 505 → 317줄 (P/Invoke + 싱글턴 + 탭 관리 유지)
- PreviewWindow.Content.cs (신규): 콘텐츠 로드(LoadContent/LoadCsvContent/ParseCsvLine)
  + 타이틀바 핸들러 9개 (170줄)

빌드: 경고 0, 오류 0

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
2026-04-03 21:43:10 +09:00
parent b750849c9f
commit 4fa38a7b9e
2 changed files with 203 additions and 188 deletions

View File

@@ -0,0 +1,203 @@
using System;
using System.Collections.Generic;
using System.Data;
using System.IO;
using System.Text;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Input;
using System.Windows.Media;
namespace AxCopilot.Views;
public partial class PreviewWindow
{
// ─── 콘텐츠 로드 + 타이틀 바 ─────────────────────────────────────────────
private async void LoadContent(string filePath)
{
var ext = Path.GetExtension(filePath).ToLowerInvariant();
PreviewBrowser.Visibility = Visibility.Collapsed;
TextScroll.Visibility = Visibility.Collapsed;
DataGridContent.Visibility = Visibility.Collapsed;
EmptyMessage.Visibility = Visibility.Collapsed;
if (!File.Exists(filePath))
{
EmptyMessage.Text = "파일을 찾을 수 없습니다";
EmptyMessage.Visibility = Visibility.Visible;
return;
}
try
{
switch (ext)
{
case ".html":
case ".htm":
if (!_webViewInitialized) return; // OnLoaded에서 재시도
PreviewBrowser.Source = new Uri(filePath);
PreviewBrowser.Visibility = Visibility.Visible;
break;
case ".csv":
LoadCsvContent(filePath);
DataGridContent.Visibility = Visibility.Visible;
break;
case ".md":
if (!_webViewInitialized) return;
var mdText = File.ReadAllText(filePath);
if (mdText.Length > 50000) mdText = mdText[..50000];
var mdHtml = Services.Agent.TemplateService.RenderMarkdownToHtml(
mdText, _selectedMood ?? "modern");
PreviewBrowser.NavigateToString(mdHtml);
PreviewBrowser.Visibility = Visibility.Visible;
break;
case ".txt":
case ".json":
case ".xml":
case ".log":
var text = File.ReadAllText(filePath);
if (text.Length > 50000) text = text[..50000] + "\n\n... (이후 생략)";
TextContent.Text = text;
TextScroll.Visibility = Visibility.Visible;
break;
default:
EmptyMessage.Text = "미리보기할 수 없는 파일 형식입니다";
EmptyMessage.Visibility = Visibility.Visible;
break;
}
}
catch (Exception ex)
{
TextContent.Text = $"미리보기 오류: {ex.Message}";
TextScroll.Visibility = Visibility.Visible;
}
await System.Threading.Tasks.Task.CompletedTask; // async 경고 방지
}
private void LoadCsvContent(string filePath)
{
var lines = File.ReadAllLines(filePath);
if (lines.Length == 0) return;
var dt = new DataTable();
var headers = ParseCsvLine(lines[0]);
foreach (var h in headers)
dt.Columns.Add(h);
var maxRows = Math.Min(lines.Length, 501);
for (int i = 1; i < maxRows; i++)
{
var vals = ParseCsvLine(lines[i]);
var row = dt.NewRow();
for (int j = 0; j < Math.Min(vals.Length, headers.Length); j++)
row[j] = vals[j];
dt.Rows.Add(row);
}
DataGridContent.ItemsSource = dt.DefaultView;
}
private static string[] ParseCsvLine(string line)
{
var fields = new List<string>();
var current = new StringBuilder();
bool inQuotes = false;
for (int i = 0; i < line.Length; i++)
{
char c = line[i];
if (inQuotes)
{
if (c == '"' && i + 1 < line.Length && line[i + 1] == '"')
{ current.Append('"'); i++; }
else if (c == '"') inQuotes = false;
else current.Append(c);
}
else
{
if (c == '"') inQuotes = true;
else if (c == ',') { fields.Add(current.ToString()); current.Clear(); }
else current.Append(c);
}
}
fields.Add(current.ToString());
return fields.ToArray();
}
// ─── 타이틀 바 ──────────────────────────────────────────────
private void TitleBar_MouseLeftButtonDown(object sender, MouseButtonEventArgs e)
{
if (e.ClickCount == 2) { ToggleMaximize(); return; }
DragMove();
}
private void OpenExternalBtn_Click(object sender, MouseButtonEventArgs e)
{
e.Handled = true;
if (_activeTab == null || !File.Exists(_activeTab)) return;
try
{
System.Diagnostics.Process.Start(new System.Diagnostics.ProcessStartInfo
{
FileName = _activeTab,
UseShellExecute = true,
});
}
catch (Exception ex)
{
Services.LogService.Warn($"외부 프로그램 열기 실패: {ex.Message}");
}
}
private void MinBtn_Click(object sender, MouseButtonEventArgs e)
{
e.Handled = true;
WindowState = WindowState.Minimized;
}
private void MaxBtn_Click(object sender, MouseButtonEventArgs e)
{
e.Handled = true;
ToggleMaximize();
}
private void CloseBtn_Click(object sender, MouseButtonEventArgs e)
{
e.Handled = true;
Close();
}
private void ToggleMaximize()
{
WindowState = WindowState == WindowState.Maximized
? WindowState.Normal
: WindowState.Maximized;
}
private void TitleBtn_Enter(object sender, MouseEventArgs e)
{
if (sender is Border b)
b.Background = TryFindResource("ItemHoverBackground") as Brush
?? new SolidColorBrush(Color.FromArgb(0x18, 0xFF, 0xFF, 0xFF));
}
private void CloseBtnEnter(object sender, MouseEventArgs e)
{
if (sender is Border b)
b.Background = new SolidColorBrush(Color.FromArgb(0x44, 0xFF, 0x40, 0x40));
}
private void TitleBtn_Leave(object sender, MouseEventArgs e)
{
if (sender is Border b)
b.Background = Brushes.Transparent;
}
}

View File

@@ -314,192 +314,4 @@ public partial class PreviewWindow : Window
TitleText.Text = $"미리보기 — {Path.GetFileName(_activeTab)}";
}
// ─── 콘텐츠 로드 ────────────────────────────────────────────
private async void LoadContent(string filePath)
{
var ext = Path.GetExtension(filePath).ToLowerInvariant();
PreviewBrowser.Visibility = Visibility.Collapsed;
TextScroll.Visibility = Visibility.Collapsed;
DataGridContent.Visibility = Visibility.Collapsed;
EmptyMessage.Visibility = Visibility.Collapsed;
if (!File.Exists(filePath))
{
EmptyMessage.Text = "파일을 찾을 수 없습니다";
EmptyMessage.Visibility = Visibility.Visible;
return;
}
try
{
switch (ext)
{
case ".html":
case ".htm":
if (!_webViewInitialized) return; // OnLoaded에서 재시도
PreviewBrowser.Source = new Uri(filePath);
PreviewBrowser.Visibility = Visibility.Visible;
break;
case ".csv":
LoadCsvContent(filePath);
DataGridContent.Visibility = Visibility.Visible;
break;
case ".md":
if (!_webViewInitialized) return;
var mdText = File.ReadAllText(filePath);
if (mdText.Length > 50000) mdText = mdText[..50000];
var mdHtml = Services.Agent.TemplateService.RenderMarkdownToHtml(
mdText, _selectedMood ?? "modern");
PreviewBrowser.NavigateToString(mdHtml);
PreviewBrowser.Visibility = Visibility.Visible;
break;
case ".txt":
case ".json":
case ".xml":
case ".log":
var text = File.ReadAllText(filePath);
if (text.Length > 50000) text = text[..50000] + "\n\n... (이후 생략)";
TextContent.Text = text;
TextScroll.Visibility = Visibility.Visible;
break;
default:
EmptyMessage.Text = "미리보기할 수 없는 파일 형식입니다";
EmptyMessage.Visibility = Visibility.Visible;
break;
}
}
catch (Exception ex)
{
TextContent.Text = $"미리보기 오류: {ex.Message}";
TextScroll.Visibility = Visibility.Visible;
}
await System.Threading.Tasks.Task.CompletedTask; // async 경고 방지
}
private void LoadCsvContent(string filePath)
{
var lines = File.ReadAllLines(filePath);
if (lines.Length == 0) return;
var dt = new DataTable();
var headers = ParseCsvLine(lines[0]);
foreach (var h in headers)
dt.Columns.Add(h);
var maxRows = Math.Min(lines.Length, 501);
for (int i = 1; i < maxRows; i++)
{
var vals = ParseCsvLine(lines[i]);
var row = dt.NewRow();
for (int j = 0; j < Math.Min(vals.Length, headers.Length); j++)
row[j] = vals[j];
dt.Rows.Add(row);
}
DataGridContent.ItemsSource = dt.DefaultView;
}
private static string[] ParseCsvLine(string line)
{
var fields = new List<string>();
var current = new StringBuilder();
bool inQuotes = false;
for (int i = 0; i < line.Length; i++)
{
char c = line[i];
if (inQuotes)
{
if (c == '"' && i + 1 < line.Length && line[i + 1] == '"')
{ current.Append('"'); i++; }
else if (c == '"') inQuotes = false;
else current.Append(c);
}
else
{
if (c == '"') inQuotes = true;
else if (c == ',') { fields.Add(current.ToString()); current.Clear(); }
else current.Append(c);
}
}
fields.Add(current.ToString());
return fields.ToArray();
}
// ─── 타이틀 바 ──────────────────────────────────────────────
private void TitleBar_MouseLeftButtonDown(object sender, MouseButtonEventArgs e)
{
if (e.ClickCount == 2) { ToggleMaximize(); return; }
DragMove();
}
private void OpenExternalBtn_Click(object sender, MouseButtonEventArgs e)
{
e.Handled = true;
if (_activeTab == null || !File.Exists(_activeTab)) return;
try
{
System.Diagnostics.Process.Start(new System.Diagnostics.ProcessStartInfo
{
FileName = _activeTab,
UseShellExecute = true,
});
}
catch (Exception ex)
{
Services.LogService.Warn($"외부 프로그램 열기 실패: {ex.Message}");
}
}
private void MinBtn_Click(object sender, MouseButtonEventArgs e)
{
e.Handled = true;
WindowState = WindowState.Minimized;
}
private void MaxBtn_Click(object sender, MouseButtonEventArgs e)
{
e.Handled = true;
ToggleMaximize();
}
private void CloseBtn_Click(object sender, MouseButtonEventArgs e)
{
e.Handled = true;
Close();
}
private void ToggleMaximize()
{
WindowState = WindowState == WindowState.Maximized
? WindowState.Normal
: WindowState.Maximized;
}
private void TitleBtn_Enter(object sender, MouseEventArgs e)
{
if (sender is Border b)
b.Background = TryFindResource("ItemHoverBackground") as Brush
?? new SolidColorBrush(Color.FromArgb(0x18, 0xFF, 0xFF, 0xFF));
}
private void CloseBtnEnter(object sender, MouseEventArgs e)
{
if (sender is Border b)
b.Background = new SolidColorBrush(Color.FromArgb(0x44, 0xFF, 0x40, 0x40));
}
private void TitleBtn_Leave(object sender, MouseEventArgs e)
{
if (sender is Border b)
b.Background = Brushes.Transparent;
}
}