[v2.0.0] AgentSettingsPanel 프리셋 섹션 추가
AgentSettingsPanel.xaml (+46줄): - 프리셋 섹션 신규 추가 (MCP 서버 ↔ 고급 사이) - "새 프리셋 저장" 버튼 (BtnPresetSave, 보라 아이콘) - "프리셋 관리 →" 버튼 (BtnPresetManage, 화살표 아이콘) - 호버 스타일 DynamicResource 적용 AgentSettingsPanel.xaml.cs (+10줄): - PresetSaveRequested / PresetManageRequested Action 콜백 프로퍼티 추가 - BtnPresetSave_Click / BtnPresetManage_Click 핸들러 추가 ChatWindow.CustomPresets.cs (+110줄): - ShowPresetManagePopup() 메서드 신규 구현 · 현재 탭의 커스텀 프리셋 목록을 Popup으로 표시 · 각 항목에 편집(✏)·삭제(🗑) 아이콘 인라인 배치 · "새 프리셋 추가" 단축 버튼 하단 고정 · PlacementMode.Left로 설정 패널 왼쪽에 앵커 ChatWindow.MoodMenu.cs (+2줄): - ToggleSettingsPanel() 내 PresetSaveRequested·PresetManageRequested 콜백 연결 빌드: 경고 0, 오류 0
This commit is contained in:
@@ -156,6 +156,173 @@ public partial class ChatWindow
|
||||
return item;
|
||||
}
|
||||
|
||||
/// <summary>현재 탭의 커스텀 프리셋 목록 팝업을 표시합니다.</summary>
|
||||
internal void ShowPresetManagePopup()
|
||||
{
|
||||
var customPresets = Llm.CustomPresets
|
||||
.Where(c => c.Tab.Equals(_activeTab, StringComparison.OrdinalIgnoreCase))
|
||||
.ToList();
|
||||
|
||||
var primaryText = ThemeResourceHelper.Primary(this);
|
||||
var secondaryText = ThemeResourceHelper.Secondary(this);
|
||||
var menuBg = ThemeResourceHelper.Background(this);
|
||||
var borderBrush = ThemeResourceHelper.Border(this);
|
||||
var hoverBg = ThemeResourceHelper.HoverBg(this);
|
||||
|
||||
var popup = new Popup
|
||||
{
|
||||
PlacementTarget = SettingsPanel,
|
||||
Placement = PlacementMode.Left,
|
||||
VerticalOffset = -40,
|
||||
StaysOpen = false,
|
||||
AllowsTransparency = true,
|
||||
};
|
||||
|
||||
var outer = new Border
|
||||
{
|
||||
Background = menuBg,
|
||||
CornerRadius = new CornerRadius(12),
|
||||
BorderBrush = borderBrush,
|
||||
BorderThickness = new Thickness(1),
|
||||
Padding = new Thickness(4),
|
||||
MinWidth = 230,
|
||||
MaxHeight = 340,
|
||||
Effect = new System.Windows.Media.Effects.DropShadowEffect
|
||||
{
|
||||
BlurRadius = 16, ShadowDepth = 2, Opacity = 0.35, Color = Colors.Black,
|
||||
},
|
||||
};
|
||||
|
||||
var sv = new ScrollViewer
|
||||
{
|
||||
VerticalScrollBarVisibility = ScrollBarVisibility.Auto,
|
||||
HorizontalScrollBarVisibility = ScrollBarVisibility.Disabled,
|
||||
};
|
||||
|
||||
var stack = new StackPanel { Margin = new Thickness(4) };
|
||||
|
||||
// 헤더
|
||||
stack.Children.Add(new TextBlock
|
||||
{
|
||||
Text = $"{_activeTab} 탭 프리셋 ({customPresets.Count}개)",
|
||||
FontSize = 12,
|
||||
FontWeight = FontWeights.SemiBold,
|
||||
Foreground = primaryText,
|
||||
Margin = new Thickness(8, 8, 8, 6),
|
||||
});
|
||||
|
||||
if (customPresets.Count == 0)
|
||||
{
|
||||
stack.Children.Add(new TextBlock
|
||||
{
|
||||
Text = "커스텀 프리셋이 없습니다.",
|
||||
FontSize = 12,
|
||||
Foreground = secondaryText,
|
||||
Margin = new Thickness(8, 0, 8, 8),
|
||||
});
|
||||
}
|
||||
else
|
||||
{
|
||||
foreach (var cp in customPresets)
|
||||
{
|
||||
var capturedCp = cp;
|
||||
|
||||
var row = new Border
|
||||
{
|
||||
Background = Brushes.Transparent,
|
||||
CornerRadius = new CornerRadius(6),
|
||||
Padding = new Thickness(6, 5, 6, 5),
|
||||
Cursor = Cursors.Hand,
|
||||
};
|
||||
row.MouseEnter += (s, _) => { if (s is Border b) b.Background = hoverBg; };
|
||||
row.MouseLeave += (s, _) => { if (s is Border b) b.Background = Brushes.Transparent; };
|
||||
|
||||
var rowGrid = new Grid();
|
||||
rowGrid.ColumnDefinitions.Add(new ColumnDefinition { Width = new GridLength(1, GridUnitType.Star) });
|
||||
rowGrid.ColumnDefinitions.Add(new ColumnDefinition { Width = GridLength.Auto });
|
||||
rowGrid.ColumnDefinitions.Add(new ColumnDefinition { Width = GridLength.Auto });
|
||||
|
||||
rowGrid.Children.Add(new TextBlock
|
||||
{
|
||||
Text = capturedCp.Label,
|
||||
FontSize = 12,
|
||||
Foreground = primaryText,
|
||||
VerticalAlignment = VerticalAlignment.Center,
|
||||
TextTrimming = TextTrimming.CharacterEllipsis,
|
||||
});
|
||||
|
||||
var editIcon = new TextBlock
|
||||
{
|
||||
Text = "\uE70F",
|
||||
FontFamily = ThemeResourceHelper.SegoeMdl2,
|
||||
FontSize = 12,
|
||||
Foreground = secondaryText,
|
||||
VerticalAlignment = VerticalAlignment.Center,
|
||||
Cursor = Cursors.Hand,
|
||||
Margin = new Thickness(8, 0, 4, 0),
|
||||
};
|
||||
Grid.SetColumn(editIcon, 1);
|
||||
editIcon.MouseLeftButtonDown += (_, _) =>
|
||||
{
|
||||
popup.IsOpen = false;
|
||||
var entry = Llm.CustomPresets.FirstOrDefault(c => c.Id == capturedCp.Id);
|
||||
if (entry != null) ShowCustomPresetDialog(entry);
|
||||
};
|
||||
|
||||
var delIcon = new TextBlock
|
||||
{
|
||||
Text = "\uE74D",
|
||||
FontFamily = ThemeResourceHelper.SegoeMdl2,
|
||||
FontSize = 12,
|
||||
Foreground = new SolidColorBrush(Color.FromRgb(0xEF, 0x44, 0x44)),
|
||||
VerticalAlignment = VerticalAlignment.Center,
|
||||
Cursor = Cursors.Hand,
|
||||
Margin = new Thickness(4, 0, 0, 0),
|
||||
};
|
||||
Grid.SetColumn(delIcon, 2);
|
||||
delIcon.MouseLeftButtonDown += (_, _) =>
|
||||
{
|
||||
popup.IsOpen = false;
|
||||
var result = CustomMessageBox.Show(
|
||||
$"'{capturedCp.Label}' 프리셋을 삭제하시겠습니까?",
|
||||
"프리셋 삭제", MessageBoxButton.YesNo, MessageBoxImage.Question);
|
||||
if (result == MessageBoxResult.Yes)
|
||||
{
|
||||
Llm.CustomPresets.RemoveAll(c => c.Id == capturedCp.Id);
|
||||
_settings.Save();
|
||||
BuildTopicButtons();
|
||||
}
|
||||
};
|
||||
|
||||
rowGrid.Children.Add(editIcon);
|
||||
rowGrid.Children.Add(delIcon);
|
||||
row.Child = rowGrid;
|
||||
stack.Children.Add(row);
|
||||
}
|
||||
}
|
||||
|
||||
// 구분선 + 새 프리셋 추가
|
||||
stack.Children.Add(new Border
|
||||
{
|
||||
Height = 1,
|
||||
Background = borderBrush,
|
||||
Margin = new Thickness(4, 4, 4, 4),
|
||||
});
|
||||
|
||||
var addItem = CreateContextMenuItem("\uE710", "새 프리셋 추가", primaryText, secondaryText);
|
||||
addItem.MouseLeftButtonDown += (_, _) =>
|
||||
{
|
||||
popup.IsOpen = false;
|
||||
ShowCustomPresetDialog(null);
|
||||
};
|
||||
stack.Children.Add(addItem);
|
||||
|
||||
sv.Content = stack;
|
||||
outer.Child = sv;
|
||||
popup.Child = outer;
|
||||
popup.IsOpen = true;
|
||||
}
|
||||
|
||||
/// <summary>대화 주제 선택 — 프리셋 시스템 프롬프트 + 카테고리 적용.</summary>
|
||||
private void SelectTopic(Services.TopicPreset preset)
|
||||
{
|
||||
|
||||
@@ -448,9 +448,11 @@ public partial class ChatWindow
|
||||
SettingsPanel.SettingsChanged -= OnSettingsPanelChanged;
|
||||
SettingsPanel.SettingsChanged += OnSettingsPanelChanged;
|
||||
// 콜백 연결 — ChatWindow 기존 구현에 위임
|
||||
SettingsPanel.ServiceSelectorRequested = () => BtnModelSelector_Click(BtnModelSelector, new System.Windows.RoutedEventArgs());
|
||||
SettingsPanel.ModelSelectorRequested = () => BtnModelSelector_Click(BtnModelSelector, new System.Windows.RoutedEventArgs());
|
||||
SettingsPanel.ServiceSelectorRequested = () => BtnModelSelector_Click(BtnModelSelector, new System.Windows.RoutedEventArgs());
|
||||
SettingsPanel.ModelSelectorRequested = () => BtnModelSelector_Click(BtnModelSelector, new System.Windows.RoutedEventArgs());
|
||||
SettingsPanel.WorkFolderBrowseRequested = () => BrowseWorkFolder();
|
||||
SettingsPanel.PresetSaveRequested = () => ShowCustomPresetDialog(null);
|
||||
SettingsPanel.PresetManageRequested = () => ShowPresetManagePopup();
|
||||
SettingsPanel.IsOpen = true;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -351,6 +351,63 @@
|
||||
|
||||
<Border Height="1" Background="{DynamicResource BorderColor}" Margin="0,8,0,16"/>
|
||||
|
||||
<!-- ═══ 프리셋 ═══ -->
|
||||
<TextBlock Text="프리셋" FontSize="13" FontWeight="SemiBold"
|
||||
Foreground="{DynamicResource PrimaryText}" Margin="0,0,0,8"/>
|
||||
|
||||
<!-- 새 프리셋 저장 -->
|
||||
<Border x:Name="BtnPresetSave"
|
||||
CornerRadius="8" Padding="10,8" Margin="0,0,0,6" Cursor="Hand"
|
||||
MouseLeftButtonUp="BtnPresetSave_Click">
|
||||
<Border.Style>
|
||||
<Style TargetType="Border">
|
||||
<Setter Property="Background" Value="{DynamicResource ItemBackground}"/>
|
||||
<Style.Triggers>
|
||||
<Trigger Property="IsMouseOver" Value="True">
|
||||
<Setter Property="Background" Value="{DynamicResource ItemHoverBackground}"/>
|
||||
</Trigger>
|
||||
</Style.Triggers>
|
||||
</Style>
|
||||
</Border.Style>
|
||||
<StackPanel Orientation="Horizontal">
|
||||
<TextBlock Text="" FontFamily="Segoe MDL2 Assets" FontSize="13"
|
||||
Foreground="#6366F1" VerticalAlignment="Center"/>
|
||||
<TextBlock Text=" 새 프리셋 저장" FontSize="12"
|
||||
Foreground="{DynamicResource PrimaryText}" VerticalAlignment="Center"
|
||||
Margin="6,0,0,0"/>
|
||||
</StackPanel>
|
||||
</Border>
|
||||
|
||||
<!-- 프리셋 관리 -->
|
||||
<Border x:Name="BtnPresetManage"
|
||||
CornerRadius="8" Padding="10,8" Margin="0,0,0,8" Cursor="Hand"
|
||||
MouseLeftButtonUp="BtnPresetManage_Click">
|
||||
<Border.Style>
|
||||
<Style TargetType="Border">
|
||||
<Setter Property="Background" Value="{DynamicResource ItemBackground}"/>
|
||||
<Style.Triggers>
|
||||
<Trigger Property="IsMouseOver" Value="True">
|
||||
<Setter Property="Background" Value="{DynamicResource ItemHoverBackground}"/>
|
||||
</Trigger>
|
||||
</Style.Triggers>
|
||||
</Style>
|
||||
</Border.Style>
|
||||
<Grid>
|
||||
<StackPanel Orientation="Horizontal">
|
||||
<TextBlock Text="" FontFamily="Segoe MDL2 Assets" FontSize="13"
|
||||
Foreground="{DynamicResource SecondaryText}" VerticalAlignment="Center"/>
|
||||
<TextBlock Text=" 프리셋 관리" FontSize="12"
|
||||
Foreground="{DynamicResource PrimaryText}" VerticalAlignment="Center"
|
||||
Margin="6,0,0,0"/>
|
||||
</StackPanel>
|
||||
<TextBlock Text="" FontFamily="Segoe MDL2 Assets" FontSize="11"
|
||||
Foreground="{DynamicResource SecondaryText}"
|
||||
HorizontalAlignment="Right" VerticalAlignment="Center"/>
|
||||
</Grid>
|
||||
</Border>
|
||||
|
||||
<Border Height="1" Background="{DynamicResource BorderColor}" Margin="0,8,0,16"/>
|
||||
|
||||
<!-- ═══ 고급 ═══ -->
|
||||
<TextBlock Text="고급" FontSize="13" FontWeight="SemiBold"
|
||||
Foreground="{DynamicResource PrimaryText}" Margin="0,0,0,8"/>
|
||||
|
||||
@@ -29,6 +29,12 @@ public partial class AgentSettingsPanel : UserControl
|
||||
/// <summary>작업 폴더 탐색 요청 콜백 (ChatWindow.BrowseWorkFolder로 위임).</summary>
|
||||
public Action? WorkFolderBrowseRequested;
|
||||
|
||||
/// <summary>새 프리셋 저장 요청 콜백 (ChatWindow.ShowCustomPresetDialog(null)로 위임).</summary>
|
||||
public Action? PresetSaveRequested;
|
||||
|
||||
/// <summary>프리셋 관리 요청 콜백 (ChatWindow.ShowPresetManagePopup()으로 위임).</summary>
|
||||
public Action? PresetManageRequested;
|
||||
|
||||
/// <summary>설정 패널 열림/닫힘 상태.</summary>
|
||||
public bool IsOpen
|
||||
{
|
||||
@@ -190,6 +196,12 @@ public partial class AgentSettingsPanel : UserControl
|
||||
WorkFolderBrowseRequested?.Invoke();
|
||||
}
|
||||
|
||||
private void BtnPresetSave_Click(object sender, System.Windows.Input.MouseButtonEventArgs e)
|
||||
=> PresetSaveRequested?.Invoke();
|
||||
|
||||
private void BtnPresetManage_Click(object sender, System.Windows.Input.MouseButtonEventArgs e)
|
||||
=> PresetManageRequested?.Invoke();
|
||||
|
||||
private void UpdateWorkFolder(SettingsService settings)
|
||||
{
|
||||
var folder = settings.Settings.Llm.WorkFolder;
|
||||
|
||||
Reference in New Issue
Block a user