Tools: one toolbar button for all tools, styled tool windows

- ToolBox: instead of a text button per tool (which did not fit the 60x60
  icon row and overlapped the icons) the HUD gets one "tools" icon button
  with a popup listing every visible tool, sorted by localized name.
- ToolWindow: chrome that follows the UI style guide (title on the left,
  close on the right, drag-to-move, double-click/maximize, edge resize),
  a status bar with buffered status/hint text, dirty-state confirmation
  and keyboard shortcuts (Ctrl+S in _Input, other keys only when no
  focused control consumed them).
- ToolTheme: denser copy of the game theme for editor toolbars;
  ToolStatusKind: status bar message kinds.
- New tools icon and the tool window texts (unsaved changes, maximize,
  close, menu title) in en/ru.
This commit is contained in:
cthangover committed 2026-10-17 14:27:19 +00:00
1 parent 6884cd5374
commit b2a0f1c10a
7 files changed
+430 -151

No files matched your search

+53
View File
@@ -0,0 +1,53 @@
using Cthangover.Core.UI.Theming;
using Godot;
namespace Cthangover.Mods.Interface.Tool
{
/// <summary>
/// Dense variant of <see cref="CthangoverTheme"/> for developer tool windows.
/// The game theme is tuned for player panels (buttons padded 18×11, inputs
/// 12×9), which makes an editor toolbar of ten controls overflow even a
/// full-HD window. This theme keeps every colour, radius and type variation
/// of the shared theme — the style guide still holds — and only tightens
/// the content margins of the boxes, so tools fit more controls without a
/// second palette. Built once by copying the shared theme and replacing its
/// flat boxes with tightened duplicates; the shared theme is never mutated.
/// </summary>
public static class ToolTheme
{
private const int MaxVerticalMargin = 5;
private const int MaxHorizontalMargin = 10;
private static Theme instance;
/// <summary>Shared dense theme instance, built lazily from the game theme.</summary>
public static Theme Get() => instance ??= Build();
private static Theme Build()
{
var theme = (Theme)CthangoverTheme.Get().Duplicate();
theme.DefaultFontSize = UiTokens.FontBody;
foreach (var type in theme.GetTypeList())
{
foreach (var name in theme.GetStyleboxList(type))
{
if (theme.GetStylebox(name, type) is not StyleBoxFlat flat)
continue;
var dense = (StyleBoxFlat)flat.Duplicate();
dense.ContentMarginTop = Mathf.Min(dense.ContentMarginTop, MaxVerticalMargin);
dense.ContentMarginBottom = Mathf.Min(dense.ContentMarginBottom, MaxVerticalMargin);
dense.ContentMarginLeft = Mathf.Min(dense.ContentMarginLeft, MaxHorizontalMargin);
dense.ContentMarginRight = Mathf.Min(dense.ContentMarginRight, MaxHorizontalMargin);
theme.SetStylebox(name, type, dense);
}
if (theme.HasFontSize("font_size", type) && theme.GetFontSize("font_size", type) > UiTokens.FontBody)
theme.SetFontSize("font_size", type, UiTokens.FontBody);
}
return theme;
}
}
}