[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)}";
|
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