[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:
203
src/AxCopilot/Views/PreviewWindow.Content.cs
Normal file
203
src/AxCopilot/Views/PreviewWindow.Content.cs
Normal 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;
|
||||
}
|
||||
}
|
||||
@@ -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;
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user