Windows Terminal 设置 UI 设计解析导航结构、外观预览窗口与级联继承在源码中的落地【免费下载链接】terminalThe new Windows Terminal and the original Windows console host, all in the same place!项目地址: https://gitcode.com/GitHub_Trending/term/terminal本文围绕 设计文档issue #1564 的 Settings UI Design展开讲清楚 Windows Terminal 设置界面的页面导航布局、各页面的完整设置项清单、带实时预览窗口的 Appearance 页设计以及键盘绑定编辑弹窗形态并结合仓库中 TerminalSettingsEditor 与 TerminalSettingsModel 的实际源码印证这些设计如何演化为今天可以运行的设置 UI——读完后你既能理解设计稿中每个页面与控件的意图也能定位到实现它的 XAML、导航标签与继承机制代码。![Settings UI 整体导航结构](https://gitcode.com/GitHub_Trending/term/terminal/blob/20588130d8ef2ba40eb56bdae88e04cce7fc5b5d/doc/specs/?utm_sourcegitcode_repo_files#1564 - Settings UI/navigation-2.png)一、设计文档的定位从 issue #1564 到三份配套规格design.md 的文档头元数据表明它由 Kayla Cinnamon 于 2020-07-13 创建、2020-08-11 最后更新对应 issue #1564。文档摘要明确了两点它描述设置 UI 每个页面的布局并给出设计稿mockup展示 UI 的外观设计稿只用于示意外观其中的布局与命名可能与最终实现不同该文档被视为最终裁决This doc should be considered the final say。同一目录下还有两份配套文档与 design.md 互为补充spec.md定义设置 UI 的基本功能——如何禁用 UI、导航项、启动方式与设置编辑保存机制cascading-settings.md探讨级联设置cascading settings与profiles.defaults如何在设置 UI 中表示。值得注意的是当时 Windows Terminal 的默认设置体验是用文本编辑器打开settings.json设置 UI 是全新引入的界面因此设计文档同时给出了导航方案对比更细粒度的分类导航 vs 与 JSON 结构对齐的导航并在 spec.md 中记录了备选方案新窗口启动、自动保存等及各自的取舍。二、顶层导航设计General / Appearance / Profiles / Keyboarddesign.md 给出的左侧导航栏顶层结构如下带星号的页面在对应功能实现后才加入GeneralStartupInteractionRenderingAppearanceGlobalColor schemesThemes*ProfilesDefaultsEnumerate profilesAdd newKeyboardMouse*Command Palette*Marketplace*在 spec.md 中还记录了另一套被否决的导航方案——与 JSON 对齐顶层只有 Globals、Profiles、Color schemes、Bindings 四项Bindings 下挂 key bindings、mouse bindings 与 command palette。最终产品选择了更细分、更易消化的分类导航理由是与其他终端更一致。对照源码今天的导航项与导航标签从 MainPage.xaml 的NavigationView.MenuItems可以看到现行导航项已演进为平铺的页面列表Launch对应原 General-Startup、Interaction、Appearance、Color Schemes、Rendering、Compatibility、Actions带 New 徽标、New Tab Menu、Extensions加上 Profiles 分组头与 Base Layerx:UidNav_ProfileDefaults即级联设置文档中把 Global 页改名后的 Base layer。导航标签常量集中定义在 NavConstants.h其中til::static_map把每个NavigationTag映射到 Segoe MDL2 Assets 图标字形例如launchTag → \xE7B5、actionsTag → \xE765Keyboard Classic。spec.md 中导航菜单底部放一个 Open the JSON file 按钮的设计也已落地MainPage.xaml 的FooterMenuItems中有OpenJsonNavItemTagOpenJson_Nav用户随时可以从 UI 回到原始 JSON 文件编辑。三、Appearance 页设计内嵌 TerminalControl 的实时预览窗口design.md 指出 Profile appearance 页需要特殊设计因为它内嵌了一个 TerminalControl 预览窗口用于实时预览外观变更。该预览窗口出现在两个页面Appearance - Color SchemesProfiles - Appearance![Appearance 页内嵌预览窗口的设计稿](https://gitcode.com/GitHub_Trending/term/terminal/blob/20588130d8ef2ba40eb56bdae88e04cce7fc5b5d/doc/specs/?utm_sourcegitcode_repo_files#1564 - Settings UI/appearance.png)源码印证预览窗口不启动真实进程PreviewConnection.cpp 实现了这个预览窗口背后的数据源它实现了一个TerminalConnection但WriteInput/Resize/Close全部为空操作Start()只通过TerminalOutput.raise(...)向渲染层写出一段固定的示例文本——包括硬重置序列RIS、Windows Terminal标题、一段仿git diff -w的彩色输出红- Windows Console、绿 Windows Terminal!、灰Write-Host !。它还根据字体是否支持 powerline 字形在PromptTextPlainC:\与PromptTextPowerline\x1b[49;34m\xe0b6…等 ANSI 序列拼出的C:\提示符之间切换并重新发送。从源码结构看预览窗口与真实终端共用同一个 TerminalControl 渲染管线只是数据源换成PreviewConnection用户每改一项颜色、字体或 acrylic 参数渲染层就会用新的设置重绘这段固定样例从而在点击保存前看到外观效果——这正是 spec.md 中在写回 settings.json 之前预览变更这一决策的实现路径。四、Keyboard 页设计绑定列表与动态生长的编辑弹窗design.md 对键盘页的描述包含三个要点页面列出所有已启用的按键绑定并提供添加与删除入口悬停某一项时出现 Edit 与 Delete 按钮点击 Edit 弹出模态框对于无参数/无 actions 的命令模态框只显示命令与按键输入区若命令带有额外参数或 actions模态框会随参数/actions 的添加动态增高。设计稿同时注明希望未来的输入框能监听按键组合即界面上增加一个 listen 按钮。![键盘绑定编辑弹窗无参数命令设计稿](https://gitcode.com/GitHub_Trending/term/terminal/blob/20588130d8ef2ba40eb56bdae88e04cce7fc5b5d/doc/specs/?utm_sourcegitcode_repo_files#1564 - Settings UI/keyboard-modal.png)今天该页面已演进为Actions 页Actions.xaml 与 EditAction 承担绑定列表 编辑弹窗的职责而 listen 构想则由 KeyChordListener 组件落地——它暴露一个Keys依赖属性DEPENDENCY_PROPERTY(Control::KeyChord, Keys)并在KeyChordTextBox_KeyDown中捕获按键事件把组合键写入KeyChord即点击输入框后直接按键即可录入组合。五、完整设置清单八个页面的控件布局design.md 的核心内容是一张覆盖全部设置项的布局表。标题行与 UI 左侧的导航视图对齐列中加粗的标题如General、Appearance、Advanced对应页面顶部的 pivot 导航。以下完整继承原文档表格General - StartupGeneral - InteractionGeneral - RenderingAppearance - GlobalAppearance - Color SchemesProfiles - GlobalProfiles - Enumerate profilesProfiles - Add newDefault profile (dropdown)Copy after selection is made (checkbox)Software rendering (checkbox)Theme (radio)Name (text box)GeneralGeneralGeneralGeneralLaunch on startup (checkbox)Copy formatting (checkbox)Screen redrawing (checkbox)Show/Hide the title bar (checkbox)Cursor color (color picker)Command line (text box)Scrollbar visibility (radio)Scrollbar visibility (radio)Launch size (radio)Word delimiters (text box)Show terminal title in title bar (checkbox)Selection background (color picker)Starting directory (browse button)Command line (browse button)Command line (browse button)Launch position (text box)Window resize behavior (checkbox)Always show tabs (checkbox)Background (color picker)Icon (browse button)Starting directory (browse button)Starting directory (browse button)Columns on first launch (number picker)Tab width mode (radio)Foreground (color picker)Tab title (text box)Name (text box)Name (text box)Rows on first launch (number picker)Hide close all tabs popup (checkbox)Black (color picker)Scrollbar visibility (radio)Icon (browse button)Icon (browse button)Automatically create new profiles when new shells are installed (checkbox)Blue (color picker)AppearanceTab title (text box)Tab title (text box)Cyan (color picker)Font face (text box)AppearanceAppearanceGreen (color picker)Font size (number picker)Retro terminal effects (checkbox)Retro terminal effects (checkbox)Purple (color picker)Font weight (dropdown)Font face (text box)Font face (text box)Red (color picker)Padding (text box)Font size (number picker)Font size (number picker)White (color picker)Cursor shape (radio)Font weight (dropdown)Font weight (dropdown)Yellow (color picker)Cursor color (color picker)Padding (text box)Padding (text box)Bright black (color picker)Cursor height (number picker)Cursor shape (radio)Cursor shape (radio)Bright blue (color picker)Color scheme (dropdown)Cursor color (color picker)Cursor color (color picker)Bright cyan (color picker)Foreground color (color picker)Cursor height (number picker)Cursor height (number picker)Bright green (color picker)Background color (color picker)Color scheme (dropdown)Color scheme (dropdown)Bright purple (color picker)Selection background color (color picker)Foreground color (color picker)Foreground color (color picker)Bright red (color picker)Enable acrylic (checkbox)Background color (color picker)Background color (color picker)Bright white (color picker)Acrylic opacity (number picker)Selection background color (color picker)Selection background color (color picker)Bright yellow (color picker)Background image (browse button)Enable acrylic (checkbox)Enable acrylic (checkbox)Background image stretch mode (radio)Acrylic opacity (number picker)Acrylic opacity (number picker)Background image alignment (dropdown)Background image (browse button)Background image (browse button)Background image opacity (number picker)Background image stretch mode (radio)Background image stretch mode (radio)Retro terminal effects (checkbox)Background image alignment (dropdown)Background image alignment (dropdown)AdvancedBackground image opacity (number picker)Background image opacity (number picker)Hide profile from dropdown (checkbox)AdvancedAdvancedSuppress title changes (checkbox)GUID (text box)GUID (text box)Antialiasing text (radio)Hide profile from dropdown (checkbox)Hide profile from dropdown (checkbox)AltGr aliasing (checkbox)Suppress title changes (checkbox)Suppress title changes (checkbox)Scroll to input when typing (checkbox)Antialiasing text (radio)Antialiasing text (radio)History size (number picker)AltGr aliasing (checkbox)AltGr aliasing (checkbox)How the profile closes (radio)Scroll to input when typing (checkbox)Scroll to input when typing (checkbox)History size (number picker)History size (number picker)How the profile closes (radio)How the profile closes (radio)表格与真实默认值 JSON 的对应关系表中每一项都对应 defaults.json 中的一个 JSON 键。该文件是系统级默认值层设计文档中system set value的来源节选可验证上述表格的取值形态Startup 组initialCols: 120、initialRows: 30、launchMode: default对应 Columns/Rows on first launch 与 Launch size 控件Interaction 组copyOnSelect: false、copyFormatting: true、wordDelimiters: /\\()\-.,:;~!#$%^*|[]{}~?\u2502对应 Copy after selection is made / Copy formatting / Word delimiters 三个控件Appearance - GlobalalwaysShowTabs: true、showTerminalTitleInTitlebar: true、tabWidthMode: equal、theme: dark对应表中 Always show tabs / Show terminal title in title bar / Tab width mode / Theme 控件Profiles 层historySize: 9001、closeOnExit: automatic、antialiasingMode: grayscale、altGrAliasing: true、snapOnInput: true等对应 Advanced pivot 下的 History size、How the profile closes、Antialiasing text、AltGr aliasing、Scroll to input when typing 控件useAcrylic: false对应 Enable acrylic。这验证了 cascading-settings.md 中所述的三级取值链用户 settings.json 值 → defaults.json 值 → 系统内建值。六、保存机制Save 按钮、未保存提示与 Portable 模式spec.md 对编辑保存的决策是实现一个 Save 按钮用户只有点击 Save 后变更才写回settings.json——与今天用文本编辑器改 JSON 并保存的行为对齐被否掉的备选方案是边改边自动保存实时生效但失去了与 JSON 工作流的对等性。当前实现与该决策一致且功能更多MainPage.xaml 底部条包含SaveButtonAccentButtonStyle 强调按钮与ResetButton左侧有一个默认Collapsed的Settings_UnsavedSettingsWarning文本Goldenrod 颜色用于提示存在未保存变更当CascadiaSettings.IsPortableMode为真时还会显示 Portable 模式说明与链接。保存/重置的实际处理逻辑在 MainPage.cpp 的SaveButton_Click/ResetButton_Click中。spec.md 同时要求整个 UI 通过完整的无障碍测试所有条目必须可被屏幕阅读器和键盘访问并全量本地化。从 TerminalSettingsEditor/Resources 下覆盖 de-DE、zh-CN、ja-JP 等十余种语言的Resources.resw目录结构看本地化要求已被落实。七、级联设置在 UI 中的表示Base layer、重置与跨 Profile 复制cascading-settings.mdCarlos Zamora 与 Kayla Cinnamon2020-11-10探讨的是既然每个设置的值可能来自 profile 自身、profiles.defaults或 defaults.json 多层声明设置 UI 应如何表达覆盖/继承关系。文档给出了一组将组合使用的 UI 提案控件下方文字标注把 Profiles 下的 Global 页改名为 Base layer覆盖了 base layer 的设置控件下方显示 Overrides Base layer. 文字标题旁提供一个带 Reset 提示的重置按钮Add New → Duplicate Profile新增 Profile 入口改为一个选择页用户可以在复制某个已有 profile与从默认设置新建之间单选随后进入的 Profile 页会按所选来源预填字段Reset Profile 按钮在 Profile 页的 Advanced pivot 底部提供 Reset to default settings清除该 profile 对象内的自定义设置优先级回落到profile.defaults然后 defaults.jsonApply to all profiles每个 Profile 的 Advanced 页提供 Copy settings to... 按钮弹出对话框以树视图列出全部 profile 设置项供勾选底部以复选框列出所有 profile 作为复制目标。文档还为每个提案对比了同类终端的做法ConEmu/Cmder 的 Clone profile、iTerm2 的 Bulk Copy from Selected Profile 等并记录了两个被否决的方案及其理由inherit下拉项每个设置变成可编辑 ComboBox、附带 inherit 选项。优点是界面不杂乱缺点是每个设置都是下拉框且颜色选择器在该模型下无法自洽锁按钮锁住 继承自 Global 且控件禁用。缺点是语义易误解锁住直觉上表示固定在本 profile与当前设计恰好相反。源码印证Has/Clear/OverrideSource 三件套cascading-settings.md 指出 XAML 层会为每个设置引入一个ContentControl包装控件并利用 TerminalSettingsModel 提供的四件套 API// Note: String and Name are replaced for each setting bool HasName(); void ClearName(); String Name(); void Name(String val);这套接口在 IInheritable.h 中由宏体系完整实现INHERITABLE_SETTING宏为每个设置生成HasNAME()判断用户是否显式设置过值、NAMEOverrideSource()返回提供当前解析值的那一层对象、ClearNAME()清回继承态与 getter/settergetter 的解析注释直接写着 fallback 顺序user set value -- inherited value -- system set value——与文档摘要中settings.json 值 → defaults.json 值 → 系统值的级联链一一对应每个设置存储为std::optionalnullopt表示必须向父层继承_parents是一个std::vectorcom_ptrTAddLeastImportantParent/AddMostImportantParent维护父子优先级NAMEOverrideSource()会沿父链回溯找到第一个显式设置该值的祖先文档特别提到INHERITABLE_NULLABLE_SETTING用于Profile.Foreground这类null 本身是合法值的可空设置用双层 optionalNullableSettingT std::optionalstd::optionalT区分未设置需继承与显式清空为 null两种状态。正是OverrideSource()让 UI 能精确回答这个值到底来自哪一层从而驱动 Overrides Base layer. 标注与每行重置按钮——设计文档中抽象的 API 需求在这里有了逐行对应的实现。八、能力与兼容性文档中的边界声明spec.md 的 Capabilities 一节明确了该功能的能力边界写作与评审设置 UI 相关代码时值得参照无障碍全新 UI 元素必须完成屏幕阅读器与键盘全路径测试且全量本地化安全 / 可靠性 / 性能功耗均不受影响兼容性默认体验从文本编辑器打开 JSON变为打开设置 UI且该行为可通过修改openSettings键绑定加settingsUI选项回退——对应今天的 Actions 页中 openSettings 的settingsUI参数未来考量hidden属性需要特殊处理理想情况下所有 profile 无论hidden与否都应出现在设置中、需要撤销功能、Marketplace 实现后加入顶层导航、导航结构随功能增长持续调整。cascading-settings.md 另指出一个兼容性取舍设置 UI 只提供 JSON 的部分对等partial parity是有意的——它是面向普通用户的简化工具若为追求全量对等而堆满选项会牺牲设置 UI 的简洁性这一核心价值。九、延伸阅读路径围绕本文主题仓库内可按以下路径继续深入设计稿三件套design.md、spec.md、cascading-settings.mdUI 实现MainPage.xaml导航、搜索框、Save/Reset 底栏、NavConstants.h导航标签与图标映射、PreviewConnection.cpp外观预览数据源、KeyChordListener.h组合键录入、ActionEntry.cpp 所在的 Actions 模型设置模型与继承机制IInheritable.h继承链与可清空设置宏、Profile.h、defaults.json系统默认值层文件头注明为自动生成修改会被忽略更宏观的模型背景可参阅 Terminal Settings Model 规格 与 TerminalSettings-spec.md。需要说明适用前提design.md 成文于 2020 年文中 Launch on startup、Launch position 等 Startup 组控件与现行 Launch.xaml 的项集合已有差异现行版本新增了 startupActions、alwaysOnTop 等defaults.json 中可见但导航分层思路、Appearance 预览窗口、Save 保存模型与级联继承表达这四大设计决策在今天的源码中仍然成立。【免费下载链接】terminalThe new Windows Terminal and the original Windows console host, all in the same place!项目地址: https://gitcode.com/GitHub_Trending/term/terminal创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考