Initial commit to new repository
This commit is contained in:
191
src/AxCopilot/Views/InputDialog.cs
Normal file
191
src/AxCopilot/Views/InputDialog.cs
Normal file
@@ -0,0 +1,191 @@
|
||||
using System.Windows;
|
||||
using System.Windows.Controls;
|
||||
using System.Windows.Input;
|
||||
using System.Windows.Media;
|
||||
using System.Windows.Media.Effects;
|
||||
using System.Windows.Shapes;
|
||||
|
||||
namespace AxCopilot.Views;
|
||||
|
||||
/// <summary>테마에 맞는 커스텀 텍스트 입력 다이얼로그.</summary>
|
||||
internal sealed class InputDialog : Window
|
||||
{
|
||||
private readonly TextBox _textBox;
|
||||
public string ResponseText => _textBox.Text;
|
||||
|
||||
public InputDialog(string title, string prompt, string defaultValue = "", string placeholder = "")
|
||||
{
|
||||
WindowStartupLocation = WindowStartupLocation.CenterOwner;
|
||||
ResizeMode = ResizeMode.NoResize;
|
||||
WindowStyle = WindowStyle.None;
|
||||
AllowsTransparency = true;
|
||||
Background = Brushes.Transparent;
|
||||
Width = 400;
|
||||
SizeToContent = SizeToContent.Height;
|
||||
|
||||
var bg = Application.Current.TryFindResource("LauncherBackground") as Brush
|
||||
?? new SolidColorBrush(Color.FromRgb(0x1A, 0x1B, 0x2E));
|
||||
var borderBrush = Application.Current.TryFindResource("BorderColor") as Brush ?? Brushes.Gray;
|
||||
var primaryText = Application.Current.TryFindResource("PrimaryText") as Brush ?? Brushes.White;
|
||||
var secondaryText = Application.Current.TryFindResource("SecondaryText") as Brush ?? Brushes.Gray;
|
||||
var accentBrush = Application.Current.TryFindResource("AccentColor") as Brush ?? Brushes.CornflowerBlue;
|
||||
var itemBg = Application.Current.TryFindResource("ItemBackground") as Brush
|
||||
?? new SolidColorBrush(Color.FromRgb(0x2A, 0x2B, 0x3E));
|
||||
|
||||
// 외부 컨테이너 (그림자 + 둥근 모서리)
|
||||
var outerBorder = new Border
|
||||
{
|
||||
Background = bg,
|
||||
BorderBrush = borderBrush,
|
||||
BorderThickness = new Thickness(1),
|
||||
CornerRadius = new CornerRadius(14),
|
||||
Margin = new Thickness(16),
|
||||
Effect = new DropShadowEffect
|
||||
{
|
||||
BlurRadius = 24, ShadowDepth = 6, Opacity = 0.35,
|
||||
Color = Colors.Black, Direction = 270,
|
||||
},
|
||||
};
|
||||
|
||||
var stack = new StackPanel { Margin = new Thickness(24, 20, 24, 20) };
|
||||
|
||||
// 타이틀 행 (아이콘 + 제목)
|
||||
var titlePanel = new StackPanel { Orientation = Orientation.Horizontal, Margin = new Thickness(0, 0, 0, 16) };
|
||||
titlePanel.Children.Add(new TextBlock
|
||||
{
|
||||
Text = "\uE8AC", // 편집 아이콘
|
||||
FontFamily = new FontFamily("Segoe MDL2 Assets"),
|
||||
FontSize = 16, Foreground = accentBrush,
|
||||
VerticalAlignment = VerticalAlignment.Center,
|
||||
Margin = new Thickness(0, 0, 10, 0),
|
||||
});
|
||||
titlePanel.Children.Add(new TextBlock
|
||||
{
|
||||
Text = title, FontSize = 15, FontWeight = FontWeights.SemiBold,
|
||||
Foreground = primaryText, VerticalAlignment = VerticalAlignment.Center,
|
||||
});
|
||||
stack.Children.Add(titlePanel);
|
||||
|
||||
// 프롬프트
|
||||
stack.Children.Add(new TextBlock
|
||||
{
|
||||
Text = prompt, FontSize = 12.5, Foreground = secondaryText,
|
||||
Margin = new Thickness(0, 0, 0, 8),
|
||||
});
|
||||
|
||||
// 텍스트 입력 (둥근 테두리 + 플레이스홀더)
|
||||
_textBox = new TextBox
|
||||
{
|
||||
Text = defaultValue,
|
||||
FontSize = 13,
|
||||
Padding = new Thickness(14, 8, 14, 8),
|
||||
Foreground = primaryText,
|
||||
Background = Brushes.Transparent,
|
||||
CaretBrush = accentBrush,
|
||||
BorderThickness = new Thickness(0),
|
||||
BorderBrush = Brushes.Transparent,
|
||||
};
|
||||
_textBox.KeyDown += (_, e) =>
|
||||
{
|
||||
if (e.Key == Key.Enter) { DialogResult = true; Close(); }
|
||||
if (e.Key == Key.Escape) { DialogResult = false; Close(); }
|
||||
};
|
||||
|
||||
// 플레이스홀더 오버레이
|
||||
var placeholderBlock = new TextBlock
|
||||
{
|
||||
Text = placeholder,
|
||||
FontSize = 13,
|
||||
Foreground = secondaryText,
|
||||
Opacity = 0.5,
|
||||
IsHitTestVisible = false,
|
||||
VerticalAlignment = VerticalAlignment.Center,
|
||||
Padding = new Thickness(14, 8, 14, 8),
|
||||
Visibility = string.IsNullOrEmpty(defaultValue) && !string.IsNullOrEmpty(placeholder)
|
||||
? Visibility.Visible : Visibility.Collapsed,
|
||||
};
|
||||
_textBox.TextChanged += (_, _) =>
|
||||
placeholderBlock.Visibility = string.IsNullOrEmpty(_textBox.Text) ? Visibility.Visible : Visibility.Collapsed;
|
||||
|
||||
var inputGrid = new Grid();
|
||||
inputGrid.Children.Add(_textBox);
|
||||
inputGrid.Children.Add(placeholderBlock);
|
||||
|
||||
var inputBorder = new Border
|
||||
{
|
||||
CornerRadius = new CornerRadius(10),
|
||||
BorderBrush = borderBrush,
|
||||
BorderThickness = new Thickness(1),
|
||||
Background = itemBg,
|
||||
Child = inputGrid,
|
||||
};
|
||||
// 포커스 시 액센트 테두리
|
||||
_textBox.GotFocus += (_, _) => inputBorder.BorderBrush = accentBrush;
|
||||
_textBox.LostFocus += (_, _) => inputBorder.BorderBrush = borderBrush;
|
||||
stack.Children.Add(inputBorder);
|
||||
|
||||
// 버튼 패널
|
||||
var btnPanel = new StackPanel
|
||||
{
|
||||
Orientation = Orientation.Horizontal,
|
||||
HorizontalAlignment = HorizontalAlignment.Right,
|
||||
Margin = new Thickness(0, 18, 0, 0),
|
||||
};
|
||||
|
||||
var cancelBtn = CreateButton("취소", Brushes.Transparent, secondaryText, borderBrush);
|
||||
cancelBtn.Click += (_, _) => { DialogResult = false; Close(); };
|
||||
btnPanel.Children.Add(cancelBtn);
|
||||
|
||||
var okBtn = CreateButton("확인", accentBrush, Brushes.White, null);
|
||||
okBtn.Click += (_, _) => { DialogResult = true; Close(); };
|
||||
btnPanel.Children.Add(okBtn);
|
||||
|
||||
stack.Children.Add(btnPanel);
|
||||
outerBorder.Child = stack;
|
||||
Content = outerBorder;
|
||||
|
||||
// 드래그 이동 (제목 영역)
|
||||
titlePanel.MouseLeftButtonDown += (_, e) => { if (e.ClickCount == 1) DragMove(); };
|
||||
|
||||
Loaded += (_, _) => { _textBox.Focus(); _textBox.SelectAll(); };
|
||||
}
|
||||
|
||||
private static Button CreateButton(string text, Brush background, Brush foreground, Brush? borderBrush)
|
||||
{
|
||||
var btn = new Button
|
||||
{
|
||||
Cursor = Cursors.Hand,
|
||||
Margin = new Thickness(0, 0, 0, 0),
|
||||
};
|
||||
if (text == "취소") btn.Margin = new Thickness(0, 0, 8, 0);
|
||||
|
||||
// 커스텀 템플릿 (둥근 버튼)
|
||||
var template = new ControlTemplate(typeof(Button));
|
||||
var bdFactory = new FrameworkElementFactory(typeof(Border));
|
||||
bdFactory.SetValue(Border.BackgroundProperty, background);
|
||||
bdFactory.SetValue(Border.CornerRadiusProperty, new CornerRadius(8));
|
||||
bdFactory.SetValue(Border.PaddingProperty, new Thickness(20, 8, 20, 8));
|
||||
bdFactory.Name = "Bd";
|
||||
if (borderBrush != null)
|
||||
{
|
||||
bdFactory.SetValue(Border.BorderBrushProperty, borderBrush);
|
||||
bdFactory.SetValue(Border.BorderThicknessProperty, new Thickness(1));
|
||||
}
|
||||
var cpFactory = new FrameworkElementFactory(typeof(ContentPresenter));
|
||||
cpFactory.SetValue(ContentPresenter.HorizontalAlignmentProperty, HorizontalAlignment.Center);
|
||||
cpFactory.SetValue(ContentPresenter.VerticalAlignmentProperty, VerticalAlignment.Center);
|
||||
bdFactory.AppendChild(cpFactory);
|
||||
template.VisualTree = bdFactory;
|
||||
|
||||
var hoverTrigger = new Trigger { Property = UIElement.IsMouseOverProperty, Value = true };
|
||||
hoverTrigger.Setters.Add(new Setter(UIElement.OpacityProperty, 0.85));
|
||||
template.Triggers.Add(hoverTrigger);
|
||||
|
||||
btn.Template = template;
|
||||
btn.Content = new TextBlock
|
||||
{
|
||||
Text = text, FontSize = 13, Foreground = foreground,
|
||||
};
|
||||
return btn;
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user