Files
QuickClaude/DarkMenu.cs
T
2026-10-09 11:32:32 -04:00

102 lines
4.4 KiB
C#

using System;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Controls.Primitives;
using System.Windows.Input;
namespace QuickClaude
{
// Right-click menu in QuickClaude's own look: dark, square, Consolas, no theme chrome or blue highlight.
public static class DarkMenu
{
// target: the text box whose Cut/Copy/Paste the menu should offer (null for none).
public static ContextMenu Make(TextBox target, Action newConversation)
{
var menu = new ContextMenu
{
Template = MenuTemplate,
FontFamily = MainWindow.Mono,
FontSize = MainWindow.TextSize,
Foreground = ConfirmWindow.Text,
FocusVisualStyle = null,
HasDropShadow = false
};
if (target != null)
{
if (!target.IsReadOnly) menu.Items.Add(Item("Cut", ApplicationCommands.Cut, target));
menu.Items.Add(Item("Copy", ApplicationCommands.Copy, target));
if (!target.IsReadOnly) menu.Items.Add(Item("Paste", ApplicationCommands.Paste, target));
menu.Items.Add(new Separator { Template = SeparatorTemplate });
}
var fresh = Item("New conversation", null, null);
fresh.Click += (s, e) => newConversation();
menu.Items.Add(fresh);
return menu;
}
static MenuItem Item(string header, ICommand command, IInputElement target) => new MenuItem
{
Header = header,
Command = command,
CommandTarget = target,
Template = ItemTemplate,
FocusVisualStyle = null,
Foreground = ConfirmWindow.Text
};
static readonly ControlTemplate MenuTemplate = MakeMenuTemplate();
static readonly ControlTemplate ItemTemplate = MakeItemTemplate();
static readonly ControlTemplate SeparatorTemplate = MakeSeparatorTemplate();
static ControlTemplate MakeMenuTemplate()
{
var bd = new FrameworkElementFactory(typeof(Border));
bd.SetValue(Border.BackgroundProperty, ConfirmWindow.Panel);
bd.SetValue(Border.BorderBrushProperty, ConfirmWindow.Edge);
bd.SetValue(Border.BorderThicknessProperty, new Thickness(1));
bd.SetValue(Border.PaddingProperty, new Thickness(0, 2, 0, 2));
var items = new FrameworkElementFactory(typeof(StackPanel));
items.SetValue(Panel.IsItemsHostProperty, true);
bd.AppendChild(items);
var t = new ControlTemplate(typeof(ContextMenu)) { VisualTree = bd };
t.Seal();
return t;
}
// Header only: no icon column, no gesture text. Faint fill when highlighted, dimmed when disabled.
static ControlTemplate MakeItemTemplate()
{
var bd = new FrameworkElementFactory(typeof(Border), "bd");
bd.SetValue(Border.BackgroundProperty, System.Windows.Media.Brushes.Transparent);
bd.SetValue(Border.PaddingProperty, new Thickness(10, 3, 16, 3));
var cp = new FrameworkElementFactory(typeof(ContentPresenter));
cp.SetValue(ContentPresenter.ContentSourceProperty, "Header");
cp.SetValue(ContentPresenter.RecognizesAccessKeyProperty, true);
bd.AppendChild(cp);
var t = new ControlTemplate(typeof(MenuItem)) { VisualTree = bd };
var hi = new Trigger { Property = MenuItem.IsHighlightedProperty, Value = true };
hi.Setters.Add(new Setter(Border.BackgroundProperty, ConfirmWindow.Hover, "bd"));
var off = new Trigger { Property = UIElement.IsEnabledProperty, Value = false };
off.Setters.Add(new Setter(UIElement.OpacityProperty, 0.4, "bd"));
t.Triggers.Add(hi);
t.Triggers.Add(off);
t.Seal();
return t;
}
static ControlTemplate MakeSeparatorTemplate()
{
var line = new FrameworkElementFactory(typeof(Border));
line.SetValue(FrameworkElement.HeightProperty, 1.0);
line.SetValue(FrameworkElement.MarginProperty, new Thickness(0, 3, 0, 3));
line.SetValue(Border.BackgroundProperty, ConfirmWindow.Edge);
var t = new ControlTemplate(typeof(Separator)) { VisualTree = line };
t.Seal();
return t;
}
}
}