From 3e2b94334d5b43283e49fce71d4c4f76741a1e36 Mon Sep 17 00:00:00 2001 From: Dustin Howett Date: Fri, 11 Dec 2020 13:34:21 -0800 Subject: [PATCH] Introduce the Terminal Settings Editor (#8048) This commit introduces the terminal settings editor (to wit: the Settings UI) as a standalone project. This project, and this commit, is the result of two and a half months of work. TSE started as a hackathon project in the Microsoft 2020 Hackathon, and from there it's grown to be a bona-fide graphical settings editor. There is a lot of xaml data binding in here, a number of views and a number of view models, and a bunch of paradigms that we've been reviewing and testing out and designing and refining. Specified in #6720, #8269 Follow-up work in #6800 Closes #1564 Closes #8048 (PR) Co-authored-by: Carlos Zamora Co-authored-by: Kayla Cinnamon Co-authored-by: Alberto Medina Gutierrez Co-authored-by: John Grandle Co-authored-by: xerootg Co-authored-by: Scott Co-authored-by: Vineeth Thomas Alex Co-authored-by: Leon Liang Co-authored-by: Dustin L. Howett Signed-off-by: Dustin L. Howett --- .../actions/spell-check/dictionary/apis.txt | 8 + .../spell-check/dictionary/microsoft.txt | 1 + OpenConsole.sln | 48 ++ .../TerminalSettingsEditor/ColorSchemes.cpp | 143 ++++ .../TerminalSettingsEditor/ColorSchemes.h | 58 ++ .../TerminalSettingsEditor/ColorSchemes.idl | 27 + .../TerminalSettingsEditor/ColorSchemes.xaml | 154 ++++ .../ColorToBrushConverter.cpp | 28 + .../ColorToBrushConverter.h | 30 + .../ColorToBrushConverter.idl | 10 + .../ColorToHexConverter.cpp | 30 + .../ColorToHexConverter.h | 30 + .../ColorToHexConverter.idl | 10 + .../CommonResources.xaml | 109 +++ .../TerminalSettingsEditor/EnumEntry.h | 35 + .../TerminalSettingsEditor/EnumEntry.idl | 11 + .../FontWeightConverter.cpp | 32 + .../FontWeightConverter.h | 30 + .../FontWeightConverter.idl | 10 + .../GlobalAppearance.cpp | 31 + .../TerminalSettingsEditor/GlobalAppearance.h | 38 + .../GlobalAppearance.idl | 24 + .../GlobalAppearance.xaml | 82 ++ .../TerminalSettingsEditor/Interaction.cpp | 22 + .../TerminalSettingsEditor/Interaction.h | 34 + .../TerminalSettingsEditor/Interaction.idl | 16 + .../TerminalSettingsEditor/Interaction.xaml | 43 + .../TerminalSettingsEditor/Launch.cpp | 39 + src/cascadia/TerminalSettingsEditor/Launch.h | 40 + .../TerminalSettingsEditor/Launch.idl | 23 + .../TerminalSettingsEditor/Launch.xaml | 131 +++ .../TerminalSettingsEditor/MainPage.cpp | 316 ++++++++ .../TerminalSettingsEditor/MainPage.h | 48 ++ .../TerminalSettingsEditor/MainPage.idl | 26 + .../TerminalSettingsEditor/MainPage.xaml | 142 ++++ .../Microsoft.Terminal.Settings.Editor.def | 3 + ...Microsoft.Terminal.Settings.Editor.vcxproj | 227 ++++++ ...t.Terminal.Settings.Editor.vcxproj.filters | 53 ++ .../PercentageConverter.cpp | 32 + .../PercentageConverter.h | 30 + .../PercentageConverter.idl | 10 + .../TerminalSettingsEditor/Profiles.cpp | 224 ++++++ .../TerminalSettingsEditor/Profiles.h | 130 +++ .../TerminalSettingsEditor/Profiles.idl | 92 +++ .../TerminalSettingsEditor/Profiles.xaml | 517 ++++++++++++ .../TerminalSettingsEditor/Rendering.cpp | 22 + .../TerminalSettingsEditor/Rendering.h | 34 + .../TerminalSettingsEditor/Rendering.idl | 16 + .../TerminalSettingsEditor/Rendering.xaml | 41 + .../Resources/en-US/Resources.resw | 744 ++++++++++++++++++ src/cascadia/TerminalSettingsEditor/Utils.cpp | 34 + src/cascadia/TerminalSettingsEditor/Utils.h | 61 ++ .../TerminalSettingsEditor/ViewModelHelpers.h | 74 ++ .../ViewModelHelpers.idl.h | 13 + .../TerminalSettingsEditor/packages.config | 5 + src/cascadia/TerminalSettingsEditor/pch.cpp | 1 + src/cascadia/TerminalSettingsEditor/pch.h | 58 ++ 57 files changed, 4280 insertions(+) create mode 100644 src/cascadia/TerminalSettingsEditor/ColorSchemes.cpp create mode 100644 src/cascadia/TerminalSettingsEditor/ColorSchemes.h create mode 100644 src/cascadia/TerminalSettingsEditor/ColorSchemes.idl create mode 100644 src/cascadia/TerminalSettingsEditor/ColorSchemes.xaml create mode 100644 src/cascadia/TerminalSettingsEditor/ColorToBrushConverter.cpp create mode 100644 src/cascadia/TerminalSettingsEditor/ColorToBrushConverter.h create mode 100644 src/cascadia/TerminalSettingsEditor/ColorToBrushConverter.idl create mode 100644 src/cascadia/TerminalSettingsEditor/ColorToHexConverter.cpp create mode 100644 src/cascadia/TerminalSettingsEditor/ColorToHexConverter.h create mode 100644 src/cascadia/TerminalSettingsEditor/ColorToHexConverter.idl create mode 100644 src/cascadia/TerminalSettingsEditor/CommonResources.xaml create mode 100644 src/cascadia/TerminalSettingsEditor/EnumEntry.h create mode 100644 src/cascadia/TerminalSettingsEditor/EnumEntry.idl create mode 100644 src/cascadia/TerminalSettingsEditor/FontWeightConverter.cpp create mode 100644 src/cascadia/TerminalSettingsEditor/FontWeightConverter.h create mode 100644 src/cascadia/TerminalSettingsEditor/FontWeightConverter.idl create mode 100644 src/cascadia/TerminalSettingsEditor/GlobalAppearance.cpp create mode 100644 src/cascadia/TerminalSettingsEditor/GlobalAppearance.h create mode 100644 src/cascadia/TerminalSettingsEditor/GlobalAppearance.idl create mode 100644 src/cascadia/TerminalSettingsEditor/GlobalAppearance.xaml create mode 100644 src/cascadia/TerminalSettingsEditor/Interaction.cpp create mode 100644 src/cascadia/TerminalSettingsEditor/Interaction.h create mode 100644 src/cascadia/TerminalSettingsEditor/Interaction.idl create mode 100644 src/cascadia/TerminalSettingsEditor/Interaction.xaml create mode 100644 src/cascadia/TerminalSettingsEditor/Launch.cpp create mode 100644 src/cascadia/TerminalSettingsEditor/Launch.h create mode 100644 src/cascadia/TerminalSettingsEditor/Launch.idl create mode 100644 src/cascadia/TerminalSettingsEditor/Launch.xaml create mode 100644 src/cascadia/TerminalSettingsEditor/MainPage.cpp create mode 100644 src/cascadia/TerminalSettingsEditor/MainPage.h create mode 100644 src/cascadia/TerminalSettingsEditor/MainPage.idl create mode 100644 src/cascadia/TerminalSettingsEditor/MainPage.xaml create mode 100644 src/cascadia/TerminalSettingsEditor/Microsoft.Terminal.Settings.Editor.def create mode 100644 src/cascadia/TerminalSettingsEditor/Microsoft.Terminal.Settings.Editor.vcxproj create mode 100644 src/cascadia/TerminalSettingsEditor/Microsoft.Terminal.Settings.Editor.vcxproj.filters create mode 100644 src/cascadia/TerminalSettingsEditor/PercentageConverter.cpp create mode 100644 src/cascadia/TerminalSettingsEditor/PercentageConverter.h create mode 100644 src/cascadia/TerminalSettingsEditor/PercentageConverter.idl create mode 100644 src/cascadia/TerminalSettingsEditor/Profiles.cpp create mode 100644 src/cascadia/TerminalSettingsEditor/Profiles.h create mode 100644 src/cascadia/TerminalSettingsEditor/Profiles.idl create mode 100644 src/cascadia/TerminalSettingsEditor/Profiles.xaml create mode 100644 src/cascadia/TerminalSettingsEditor/Rendering.cpp create mode 100644 src/cascadia/TerminalSettingsEditor/Rendering.h create mode 100644 src/cascadia/TerminalSettingsEditor/Rendering.idl create mode 100644 src/cascadia/TerminalSettingsEditor/Rendering.xaml create mode 100644 src/cascadia/TerminalSettingsEditor/Resources/en-US/Resources.resw create mode 100644 src/cascadia/TerminalSettingsEditor/Utils.cpp create mode 100644 src/cascadia/TerminalSettingsEditor/Utils.h create mode 100644 src/cascadia/TerminalSettingsEditor/ViewModelHelpers.h create mode 100644 src/cascadia/TerminalSettingsEditor/ViewModelHelpers.idl.h create mode 100644 src/cascadia/TerminalSettingsEditor/packages.config create mode 100644 src/cascadia/TerminalSettingsEditor/pch.cpp create mode 100644 src/cascadia/TerminalSettingsEditor/pch.h diff --git a/.github/actions/spell-check/dictionary/apis.txt b/.github/actions/spell-check/dictionary/apis.txt index 033ad6c32..31df31940 100644 --- a/.github/actions/spell-check/dictionary/apis.txt +++ b/.github/actions/spell-check/dictionary/apis.txt @@ -32,6 +32,7 @@ IInheritable IMap IObject IStorage +ITab ITaskbar llabs LCID @@ -63,17 +64,24 @@ semver serializer shobjidl SIZENS +GETDESKWALLPAPER +snprintf spsc sregex STDCPP strchr +Subheader +Subpage +UPDATEINIFILE syscall TBPF THEMECHANGED tmp +tolower tx UPDATEINIFILE userenv +wcsstr wcstoui wsregex XDocument diff --git a/.github/actions/spell-check/dictionary/microsoft.txt b/.github/actions/spell-check/dictionary/microsoft.txt index e803c06f6..f2419fe59 100644 --- a/.github/actions/spell-check/dictionary/microsoft.txt +++ b/.github/actions/spell-check/dictionary/microsoft.txt @@ -12,6 +12,7 @@ LKG mfcribbon microsoft microsoftonline +muxc netcore osgvsowi pgc diff --git a/OpenConsole.sln b/OpenConsole.sln index a07510593..364216a7c 100644 --- a/OpenConsole.sln +++ b/OpenConsole.sln @@ -172,6 +172,7 @@ EndProject Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "WindowsTerminal", "src\cascadia\WindowsTerminal\WindowsTerminal.vcxproj", "{CA5CAD1A-1754-4A9D-93D7-857A9D17CB1B}" ProjectSection(ProjectDependencies) = postProject {CA5CAD1A-44BD-4AC7-AC72-6CA5B3AB89ED} = {CA5CAD1A-44BD-4AC7-AC72-6CA5B3AB89ED} + {CA5CAD1A-0B5E-45C3-96A8-BB496BFE4E32} = {CA5CAD1A-0B5E-45C3-96A8-BB496BFE4E32} {CA5CAD1A-44BD-4AC7-AC72-F16E576FDD12} = {CA5CAD1A-44BD-4AC7-AC72-F16E576FDD12} {CA5CAD1A-ABCD-429C-B551-8562EC954746} = {CA5CAD1A-ABCD-429C-B551-8562EC954746} {9CBD7DFA-1754-4A9D-93D7-857A9D17CB1B} = {9CBD7DFA-1754-4A9D-93D7-857A9D17CB1B} @@ -180,6 +181,7 @@ EndProject Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "TerminalApp", "src\cascadia\TerminalApp\dll\TerminalApp.vcxproj", "{CA5CAD1A-44BD-4AC7-AC72-F16E576FDD12}" ProjectSection(ProjectDependencies) = postProject {CA5CAD1A-9A12-429C-B551-8562EC954746} = {CA5CAD1A-9A12-429C-B551-8562EC954746} + {CA5CAD1A-0B5E-45C3-96A8-BB496BFE4E32} = {CA5CAD1A-0B5E-45C3-96A8-BB496BFE4E32} {CA5CAD1A-082C-4476-9F33-94B339494076} = {CA5CAD1A-082C-4476-9F33-94B339494076} {CA5CAD1A-C46D-4588-B1C0-40F31AE9100B} = {CA5CAD1A-C46D-4588-B1C0-40F31AE9100B} {CA5CAD1A-44BD-4AC7-AC72-6CA5B3AB89ED} = {CA5CAD1A-44BD-4AC7-AC72-6CA5B3AB89ED} @@ -233,6 +235,7 @@ Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "TerminalAppLib", "src\casca ProjectSection(ProjectDependencies) = postProject {CA5CAD1A-082C-4476-9F33-94B339494076} = {CA5CAD1A-082C-4476-9F33-94B339494076} {CA5CAD1A-44BD-4AC7-AC72-6CA5B3AB89ED} = {CA5CAD1A-44BD-4AC7-AC72-6CA5B3AB89ED} + {CA5CAD1A-0B5E-45C3-96A8-BB496BFE4E32} = {CA5CAD1A-0B5E-45C3-96A8-BB496BFE4E32} EndProjectSection EndProject Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "LocalTests_TerminalApp", "src\cascadia\LocalTests_TerminalApp\TerminalApp.LocalTests.vcxproj", "{CA5CAD1A-B11C-4DDB-A4FE-C3AFAE9B5506}" @@ -315,6 +318,11 @@ Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "WpfTerminalTestNetCore", "s EndProject Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "wt", "src\cascadia\wt\wt.vcxproj", "{506FD703-BAA7-4F6E-9361-64F550EC8FCA}" EndProject +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "Microsoft.Terminal.Settings.Editor", "src\cascadia\TerminalSettingsEditor\Microsoft.Terminal.Settings.Editor.vcxproj", "{CA5CAD1A-0B5E-45C3-96A8-BB496BFE4E32}" + ProjectSection(ProjectDependencies) = postProject + {CA5CAD1A-082C-4476-9F33-94B339494076} = {CA5CAD1A-082C-4476-9F33-94B339494076} + EndProjectSection +EndProject Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "Microsoft.Terminal.Settings.Model.Lib", "src\cascadia\TerminalSettingsModel\Microsoft.Terminal.Settings.ModelLib.vcxproj", "{CA5CAD1A-D7EC-4107-B7C6-79CB77AE2907}" ProjectSection(ProjectDependencies) = postProject {CA5CAD1A-44BD-4AC7-AC72-6CA5B3AB89ED} = {CA5CAD1A-44BD-4AC7-AC72-6CA5B3AB89ED} @@ -2012,6 +2020,45 @@ Global {506FD703-BAA7-4F6E-9361-64F550EC8FCA}.Release|x64.Build.0 = Release|x64 {506FD703-BAA7-4F6E-9361-64F550EC8FCA}.Release|x86.ActiveCfg = Release|Win32 {506FD703-BAA7-4F6E-9361-64F550EC8FCA}.Release|x86.Build.0 = Release|Win32 + {CA5CAD1A-0B5E-45C3-96A8-BB496BFE4E32}.AuditMode|Any CPU.ActiveCfg = Release|x64 + {CA5CAD1A-0B5E-45C3-96A8-BB496BFE4E32}.AuditMode|Any CPU.Build.0 = Release|x64 + {CA5CAD1A-0B5E-45C3-96A8-BB496BFE4E32}.AuditMode|Any CPU.Deploy.0 = Release|x64 + {CA5CAD1A-0B5E-45C3-96A8-BB496BFE4E32}.AuditMode|ARM64.ActiveCfg = Release|x64 + {CA5CAD1A-0B5E-45C3-96A8-BB496BFE4E32}.AuditMode|ARM64.Build.0 = Release|x64 + {CA5CAD1A-0B5E-45C3-96A8-BB496BFE4E32}.AuditMode|ARM64.Deploy.0 = Release|x64 + {CA5CAD1A-0B5E-45C3-96A8-BB496BFE4E32}.AuditMode|DotNet_x64Test.ActiveCfg = Release|x64 + {CA5CAD1A-0B5E-45C3-96A8-BB496BFE4E32}.AuditMode|DotNet_x64Test.Build.0 = Release|x64 + {CA5CAD1A-0B5E-45C3-96A8-BB496BFE4E32}.AuditMode|DotNet_x64Test.Deploy.0 = Release|x64 + {CA5CAD1A-0B5E-45C3-96A8-BB496BFE4E32}.AuditMode|DotNet_x86Test.ActiveCfg = Release|x64 + {CA5CAD1A-0B5E-45C3-96A8-BB496BFE4E32}.AuditMode|DotNet_x86Test.Build.0 = Release|x64 + {CA5CAD1A-0B5E-45C3-96A8-BB496BFE4E32}.AuditMode|DotNet_x86Test.Deploy.0 = Release|x64 + {CA5CAD1A-0B5E-45C3-96A8-BB496BFE4E32}.AuditMode|x64.ActiveCfg = Release|x64 + {CA5CAD1A-0B5E-45C3-96A8-BB496BFE4E32}.AuditMode|x64.Deploy.0 = Release|x64 + {CA5CAD1A-0B5E-45C3-96A8-BB496BFE4E32}.AuditMode|x86.ActiveCfg = Release|Win32 + {CA5CAD1A-0B5E-45C3-96A8-BB496BFE4E32}.AuditMode|x86.Build.0 = Release|Win32 + {CA5CAD1A-0B5E-45C3-96A8-BB496BFE4E32}.AuditMode|x86.Deploy.0 = Release|Win32 + {CA5CAD1A-0B5E-45C3-96A8-BB496BFE4E32}.Debug|Any CPU.ActiveCfg = Debug|Win32 + {CA5CAD1A-0B5E-45C3-96A8-BB496BFE4E32}.Debug|ARM64.ActiveCfg = Debug|ARM64 + {CA5CAD1A-0B5E-45C3-96A8-BB496BFE4E32}.Debug|ARM64.Build.0 = Debug|ARM64 + {CA5CAD1A-0B5E-45C3-96A8-BB496BFE4E32}.Debug|DotNet_x64Test.ActiveCfg = Debug|Win32 + {CA5CAD1A-0B5E-45C3-96A8-BB496BFE4E32}.Debug|DotNet_x86Test.ActiveCfg = Debug|Win32 + {CA5CAD1A-0B5E-45C3-96A8-BB496BFE4E32}.Debug|x64.ActiveCfg = Debug|x64 + {CA5CAD1A-0B5E-45C3-96A8-BB496BFE4E32}.Debug|x64.Build.0 = Debug|x64 + {CA5CAD1A-0B5E-45C3-96A8-BB496BFE4E32}.Debug|x64.Deploy.0 = Debug|x64 + {CA5CAD1A-0B5E-45C3-96A8-BB496BFE4E32}.Debug|x86.ActiveCfg = Debug|Win32 + {CA5CAD1A-0B5E-45C3-96A8-BB496BFE4E32}.Debug|x86.Build.0 = Debug|Win32 + {CA5CAD1A-0B5E-45C3-96A8-BB496BFE4E32}.Debug|x86.Deploy.0 = Debug|Win32 + {CA5CAD1A-0B5E-45C3-96A8-BB496BFE4E32}.Release|Any CPU.ActiveCfg = Release|Win32 + {CA5CAD1A-0B5E-45C3-96A8-BB496BFE4E32}.Release|ARM64.ActiveCfg = Release|ARM64 + {CA5CAD1A-0B5E-45C3-96A8-BB496BFE4E32}.Release|ARM64.Build.0 = Release|ARM64 + {CA5CAD1A-0B5E-45C3-96A8-BB496BFE4E32}.Release|DotNet_x64Test.ActiveCfg = Release|Win32 + {CA5CAD1A-0B5E-45C3-96A8-BB496BFE4E32}.Release|DotNet_x86Test.ActiveCfg = Release|Win32 + {CA5CAD1A-0B5E-45C3-96A8-BB496BFE4E32}.Release|x64.ActiveCfg = Release|x64 + {CA5CAD1A-0B5E-45C3-96A8-BB496BFE4E32}.Release|x64.Build.0 = Release|x64 + {CA5CAD1A-0B5E-45C3-96A8-BB496BFE4E32}.Release|x64.Deploy.0 = Release|x64 + {CA5CAD1A-0B5E-45C3-96A8-BB496BFE4E32}.Release|x86.ActiveCfg = Release|Win32 + {CA5CAD1A-0B5E-45C3-96A8-BB496BFE4E32}.Release|x86.Build.0 = Release|Win32 + {CA5CAD1A-0B5E-45C3-96A8-BB496BFE4E32}.Release|x86.Deploy.0 = Release|Win32 {CA5CAD1A-D7EC-4107-B7C6-79CB77AE2907}.AuditMode|Any CPU.ActiveCfg = AuditMode|Win32 {CA5CAD1A-D7EC-4107-B7C6-79CB77AE2907}.AuditMode|ARM64.ActiveCfg = AuditMode|ARM64 {CA5CAD1A-D7EC-4107-B7C6-79CB77AE2907}.AuditMode|ARM64.Build.0 = AuditMode|ARM64 @@ -2170,6 +2217,7 @@ Global {6BAE5851-50D5-4934-8D5E-30361A8A40F3} = {81C352DB-1818-45B7-A284-18E259F1CC87} {1588FD7C-241E-4E7D-9113-43735F3E6BAD} = {59840756-302F-44DF-AA47-441A9D673202} {506FD703-BAA7-4F6E-9361-64F550EC8FCA} = {59840756-302F-44DF-AA47-441A9D673202} + {CA5CAD1A-0B5E-45C3-96A8-BB496BFE4E32} = {59840756-302F-44DF-AA47-441A9D673202} {CA5CAD1A-D7EC-4107-B7C6-79CB77AE2907} = {59840756-302F-44DF-AA47-441A9D673202} {CA5CAD1A-082C-4476-9F33-94B339494076} = {59840756-302F-44DF-AA47-441A9D673202} {CA5CAD1A-9B68-456A-B13E-C8218070DC42} = {BDB237B6-1D1D-400F-84CC-40A58FA59C8E} diff --git a/src/cascadia/TerminalSettingsEditor/ColorSchemes.cpp b/src/cascadia/TerminalSettingsEditor/ColorSchemes.cpp new file mode 100644 index 000000000..ed229ef20 --- /dev/null +++ b/src/cascadia/TerminalSettingsEditor/ColorSchemes.cpp @@ -0,0 +1,143 @@ +// Copyright (c) Microsoft Corporation. +// Licensed under the MIT license. + +#include "pch.h" +#include "ColorSchemes.h" +#include "ColorTableEntry.g.cpp" +#include "ColorSchemes.g.cpp" +#include "ColorSchemesPageNavigationState.g.cpp" + +#include + +using namespace winrt; +using namespace winrt::Windows::UI; +using namespace winrt::Windows::UI::Xaml::Navigation; +using namespace winrt::Windows::UI::Xaml::Controls; +using namespace winrt::Windows::UI::Xaml::Media; +using namespace winrt::Windows::Foundation; +using namespace winrt::Windows::Foundation::Collections; + +namespace winrt::Microsoft::Terminal::Settings::Editor::implementation +{ + static const std::array TableColorNames = { + RS_(L"ColorScheme_Black/Header"), + RS_(L"ColorScheme_Red/Header"), + RS_(L"ColorScheme_Green/Header"), + RS_(L"ColorScheme_Yellow/Header"), + RS_(L"ColorScheme_Blue/Header"), + RS_(L"ColorScheme_Purple/Header"), + RS_(L"ColorScheme_Cyan/Header"), + RS_(L"ColorScheme_White/Header"), + RS_(L"ColorScheme_BrightBlack/Header"), + RS_(L"ColorScheme_BrightRed/Header"), + RS_(L"ColorScheme_BrightGreen/Header"), + RS_(L"ColorScheme_BrightYellow/Header"), + RS_(L"ColorScheme_BrightBlue/Header"), + RS_(L"ColorScheme_BrightPurple/Header"), + RS_(L"ColorScheme_BrightCyan/Header"), + RS_(L"ColorScheme_BrightWhite/Header") + }; + + ColorSchemes::ColorSchemes() : + _ColorSchemeList{ single_threaded_observable_vector() }, + _CurrentColorTable{ single_threaded_observable_vector() } + { + InitializeComponent(); + } + + void ColorSchemes::OnNavigatedTo(const NavigationEventArgs& e) + { + _State = e.Parameter().as(); + _UpdateColorSchemeList(); + + // Initialize our color table view model with 16 dummy colors + // so that on a ColorScheme selection change, we can loop through + // each ColorTableEntry and just change its color. Performing a + // clear and 16 appends doesn't seem to update the color pickers + // very accurately. + for (uint8_t i = 0; i < TableColorNames.size(); ++i) + { + auto entry = winrt::make(i, Windows::UI::Color{ 0, 0, 0, 0 }); + _CurrentColorTable.Append(entry); + } + } + + // Function Description: + // - Called when a different color scheme is selected. Updates our current + // color scheme and updates our currently modifiable color table. + // Arguments: + // - args: The selection changed args that tells us what's the new color scheme selected. + // Return Value: + // - + void ColorSchemes::ColorSchemeSelectionChanged(IInspectable const& /*sender*/, + SelectionChangedEventArgs const& args) + { + // Update the color scheme this page is modifying + auto str = winrt::unbox_value(args.AddedItems().GetAt(0)); + auto colorScheme = _State.Globals().ColorSchemes().Lookup(str); + CurrentColorScheme(colorScheme); + _UpdateColorTable(colorScheme); + } + + // Function Description: + // - Updates the list of all color schemes available to choose from. + // Arguments: + // - + // Return Value: + // - + void ColorSchemes::_UpdateColorSchemeList() + { + // Surprisingly, though this is called every time we navigate to the page, + // the list does not keep growing on each navigation. + const auto& colorSchemeMap{ _State.Globals().ColorSchemes() }; + for (const auto& pair : colorSchemeMap) + { + _ColorSchemeList.Append(pair.Key()); + } + } + + // Function Description: + // - Called when a ColorPicker control has selected a new color. This is specifically + // called by color pickers assigned to a color table entry. It takes the index + // that's been stuffed in the Tag property of the color picker and uses it + // to update the color table accordingly. + // Arguments: + // - sender: the color picker that raised this event. + // - args: the args that contains the new color that was picked. + // Return Value: + // - + void ColorSchemes::ColorPickerChanged(IInspectable const& sender, + ColorChangedEventArgs const& args) + { + if (auto picker = sender.try_as()) + { + if (auto tag = picker.Tag()) + { + auto index = winrt::unbox_value(tag); + CurrentColorScheme().SetColorTableEntry(index, args.NewColor()); + _CurrentColorTable.GetAt(index).Color(args.NewColor()); + } + } + } + + // Function Description: + // - Updates the currently modifiable color table based on the given current color scheme. + // Arguments: + // - colorScheme: the color scheme to retrieve the color table from + // Return Value: + // - + void ColorSchemes::_UpdateColorTable(const Model::ColorScheme& colorScheme) + { + for (uint8_t i = 0; i < TableColorNames.size(); ++i) + { + _CurrentColorTable.GetAt(i).Color(colorScheme.Table()[i]); + } + } + + ColorTableEntry::ColorTableEntry(uint8_t index, Windows::UI::Color color) + { + Name(TableColorNames[index]); + Index(winrt::box_value(index)); + Color(color); + } +} diff --git a/src/cascadia/TerminalSettingsEditor/ColorSchemes.h b/src/cascadia/TerminalSettingsEditor/ColorSchemes.h new file mode 100644 index 000000000..b5898060b --- /dev/null +++ b/src/cascadia/TerminalSettingsEditor/ColorSchemes.h @@ -0,0 +1,58 @@ +// Copyright (c) Microsoft Corporation. +// Licensed under the MIT license. + +#pragma once + +#include "ColorTableEntry.g.h" +#include "ColorSchemes.g.h" +#include "ColorSchemesPageNavigationState.g.h" +#include "Utils.h" + +namespace winrt::Microsoft::Terminal::Settings::Editor::implementation +{ + struct ColorSchemesPageNavigationState : ColorSchemesPageNavigationStateT + { + public: + ColorSchemesPageNavigationState(const Model::GlobalAppSettings& settings) : + _Globals{ settings } {} + + GETSET_PROPERTY(Model::GlobalAppSettings, Globals, nullptr); + }; + + struct ColorSchemes : ColorSchemesT + { + ColorSchemes(); + + void OnNavigatedTo(const winrt::Windows::UI::Xaml::Navigation::NavigationEventArgs& e); + + void ColorSchemeSelectionChanged(winrt::Windows::Foundation::IInspectable const& sender, winrt::Windows::UI::Xaml::Controls::SelectionChangedEventArgs const& args); + void ColorPickerChanged(winrt::Windows::Foundation::IInspectable const& sender, winrt::Windows::UI::Xaml::Controls::ColorChangedEventArgs const& args); + + GETSET_PROPERTY(Editor::ColorSchemesPageNavigationState, State, nullptr); + GETSET_PROPERTY(Windows::Foundation::Collections::IObservableVector, CurrentColorTable, nullptr); + GETSET_PROPERTY(Windows::Foundation::Collections::IObservableVector, ColorSchemeList, nullptr); + + WINRT_CALLBACK(PropertyChanged, Windows::UI::Xaml::Data::PropertyChangedEventHandler); + OBSERVABLE_GETSET_PROPERTY(winrt::Microsoft::Terminal::Settings::Model::ColorScheme, CurrentColorScheme, _PropertyChangedHandlers, nullptr); + + private: + void _UpdateColorTable(const winrt::Microsoft::Terminal::Settings::Model::ColorScheme& colorScheme); + void _UpdateColorSchemeList(); + }; + + struct ColorTableEntry : ColorTableEntryT + { + public: + ColorTableEntry(uint8_t index, Windows::UI::Color color); + + WINRT_CALLBACK(PropertyChanged, Windows::UI::Xaml::Data::PropertyChangedEventHandler); + OBSERVABLE_GETSET_PROPERTY(winrt::hstring, Name, _PropertyChangedHandlers); + OBSERVABLE_GETSET_PROPERTY(IInspectable, Index, _PropertyChangedHandlers); + OBSERVABLE_GETSET_PROPERTY(Windows::UI::Color, Color, _PropertyChangedHandlers); + }; +} + +namespace winrt::Microsoft::Terminal::Settings::Editor::factory_implementation +{ + BASIC_FACTORY(ColorSchemes); +} diff --git a/src/cascadia/TerminalSettingsEditor/ColorSchemes.idl b/src/cascadia/TerminalSettingsEditor/ColorSchemes.idl new file mode 100644 index 000000000..80f6cd622 --- /dev/null +++ b/src/cascadia/TerminalSettingsEditor/ColorSchemes.idl @@ -0,0 +1,27 @@ +// Copyright (c) Microsoft Corporation. +// Licensed under the MIT license. + +namespace Microsoft.Terminal.Settings.Editor +{ + runtimeclass ColorSchemesPageNavigationState + { + Microsoft.Terminal.Settings.Model.GlobalAppSettings Globals; + }; + + [default_interface] runtimeclass ColorSchemes : Windows.UI.Xaml.Controls.Page, Windows.UI.Xaml.Data.INotifyPropertyChanged + { + ColorSchemes(); + ColorSchemesPageNavigationState State { get; }; + + Microsoft.Terminal.Settings.Model.ColorScheme CurrentColorScheme { get; }; + Windows.Foundation.Collections.IObservableVector CurrentColorTable; + Windows.Foundation.Collections.IObservableVector ColorSchemeList { get; }; + } + + [default_interface] runtimeclass ColorTableEntry : Windows.UI.Xaml.Data.INotifyPropertyChanged + { + String Name { get; }; + IInspectable Index; + Windows.UI.Color Color; + } +} diff --git a/src/cascadia/TerminalSettingsEditor/ColorSchemes.xaml b/src/cascadia/TerminalSettingsEditor/ColorSchemes.xaml new file mode 100644 index 000000000..028eea31b --- /dev/null +++ b/src/cascadia/TerminalSettingsEditor/ColorSchemes.xaml @@ -0,0 +1,154 @@ + + + + + + + + + + 10,0,0,20 + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/src/cascadia/TerminalSettingsEditor/ColorToBrushConverter.cpp b/src/cascadia/TerminalSettingsEditor/ColorToBrushConverter.cpp new file mode 100644 index 000000000..2cdefb6eb --- /dev/null +++ b/src/cascadia/TerminalSettingsEditor/ColorToBrushConverter.cpp @@ -0,0 +1,28 @@ +// Copyright (c) Microsoft Corporation. +// Licensed under the MIT license. + +#include "pch.h" +#include "ColorToBrushConverter.h" +#include "ColorToBrushConverter.g.cpp" + +using namespace winrt::Windows; +using namespace winrt::Windows::UI::Xaml; + +namespace winrt::Microsoft::Terminal::Settings::Editor::implementation +{ + Foundation::IInspectable ColorToBrushConverter::Convert(Foundation::IInspectable const& value, + Windows::UI::Xaml::Interop::TypeName const& /* targetType */, + Foundation::IInspectable const& /* parameter */, + hstring const& /* language */) + { + return winrt::box_value(Windows::UI::Xaml::Media::SolidColorBrush(winrt::unbox_value(value))); + } + + Foundation::IInspectable ColorToBrushConverter::ConvertBack(Foundation::IInspectable const& /*value*/, + Windows::UI::Xaml::Interop::TypeName const& /* targetType */, + Foundation::IInspectable const& /*parameter*/, + hstring const& /* language */) + { + throw hresult_not_implemented(); + } +} diff --git a/src/cascadia/TerminalSettingsEditor/ColorToBrushConverter.h b/src/cascadia/TerminalSettingsEditor/ColorToBrushConverter.h new file mode 100644 index 000000000..94c20db6d --- /dev/null +++ b/src/cascadia/TerminalSettingsEditor/ColorToBrushConverter.h @@ -0,0 +1,30 @@ +// Copyright (c) Microsoft Corporation. +// Licensed under the MIT license. + +#pragma once + +#include "ColorToBrushConverter.g.h" +#include "Utils.h" + +namespace winrt::Microsoft::Terminal::Settings::Editor::implementation +{ + struct ColorToBrushConverter : ColorToBrushConverterT + { + ColorToBrushConverter() = default; + + Windows::Foundation::IInspectable Convert(Windows::Foundation::IInspectable const& value, + Windows::UI::Xaml::Interop::TypeName const& targetType, + Windows::Foundation::IInspectable const& parameter, + hstring const& language); + + Windows::Foundation::IInspectable ConvertBack(Windows::Foundation::IInspectable const& value, + Windows::UI::Xaml::Interop::TypeName const& targetType, + Windows::Foundation::IInspectable const& parameter, + hstring const& language); + }; +} + +namespace winrt::Microsoft::Terminal::Settings::Editor::factory_implementation +{ + BASIC_FACTORY(ColorToBrushConverter); +} diff --git a/src/cascadia/TerminalSettingsEditor/ColorToBrushConverter.idl b/src/cascadia/TerminalSettingsEditor/ColorToBrushConverter.idl new file mode 100644 index 000000000..fb4346e42 --- /dev/null +++ b/src/cascadia/TerminalSettingsEditor/ColorToBrushConverter.idl @@ -0,0 +1,10 @@ +// Copyright (c) Microsoft Corporation. +// Licensed under the MIT license. + +namespace Microsoft.Terminal.Settings.Editor +{ + runtimeclass ColorToBrushConverter : [default] Windows.UI.Xaml.Data.IValueConverter + { + ColorToBrushConverter(); + }; +} diff --git a/src/cascadia/TerminalSettingsEditor/ColorToHexConverter.cpp b/src/cascadia/TerminalSettingsEditor/ColorToHexConverter.cpp new file mode 100644 index 000000000..1d9379ab3 --- /dev/null +++ b/src/cascadia/TerminalSettingsEditor/ColorToHexConverter.cpp @@ -0,0 +1,30 @@ +// Copyright (c) Microsoft Corporation. +// Licensed under the MIT license. + +#include "pch.h" +#include "ColorToHexConverter.h" +#include "ColorToHexConverter.g.cpp" + +using namespace winrt::Windows; +using namespace winrt::Windows::UI::Xaml; + +namespace winrt::Microsoft::Terminal::Settings::Editor::implementation +{ + Foundation::IInspectable ColorToHexConverter::Convert(Foundation::IInspectable const& value, + Windows::UI::Xaml::Interop::TypeName const& /* targetType */, + Foundation::IInspectable const& /* parameter */, + hstring const& /* language */) + { + til::color color{ winrt::unbox_value(value) }; + auto hex = winrt::to_hstring(color.ToHexString().data()); + return winrt::box_value(hex); + } + + Foundation::IInspectable ColorToHexConverter::ConvertBack(Foundation::IInspectable const& /*value*/, + Windows::UI::Xaml::Interop::TypeName const& /* targetType */, + Foundation::IInspectable const& /*parameter*/, + hstring const& /* language */) + { + throw hresult_not_implemented(); + } +} diff --git a/src/cascadia/TerminalSettingsEditor/ColorToHexConverter.h b/src/cascadia/TerminalSettingsEditor/ColorToHexConverter.h new file mode 100644 index 000000000..53e2963df --- /dev/null +++ b/src/cascadia/TerminalSettingsEditor/ColorToHexConverter.h @@ -0,0 +1,30 @@ +// Copyright (c) Microsoft Corporation. +// Licensed under the MIT license. + +#pragma once + +#include "ColorToHexConverter.g.h" +#include "Utils.h" + +namespace winrt::Microsoft::Terminal::Settings::Editor::implementation +{ + struct ColorToHexConverter : ColorToHexConverterT + { + ColorToHexConverter() = default; + + Windows::Foundation::IInspectable Convert(Windows::Foundation::IInspectable const& value, + Windows::UI::Xaml::Interop::TypeName const& targetType, + Windows::Foundation::IInspectable const& parameter, + hstring const& language); + + Windows::Foundation::IInspectable ConvertBack(Windows::Foundation::IInspectable const& value, + Windows::UI::Xaml::Interop::TypeName const& targetType, + Windows::Foundation::IInspectable const& parameter, + hstring const& language); + }; +} + +namespace winrt::Microsoft::Terminal::Settings::Editor::factory_implementation +{ + BASIC_FACTORY(ColorToHexConverter); +} diff --git a/src/cascadia/TerminalSettingsEditor/ColorToHexConverter.idl b/src/cascadia/TerminalSettingsEditor/ColorToHexConverter.idl new file mode 100644 index 000000000..e16d4656f --- /dev/null +++ b/src/cascadia/TerminalSettingsEditor/ColorToHexConverter.idl @@ -0,0 +1,10 @@ +// Copyright (c) Microsoft Corporation. +// Licensed under the MIT license. + +namespace Microsoft.Terminal.Settings.Editor +{ + runtimeclass ColorToHexConverter : [default] Windows.UI.Xaml.Data.IValueConverter + { + ColorToHexConverter(); + }; +} diff --git a/src/cascadia/TerminalSettingsEditor/CommonResources.xaml b/src/cascadia/TerminalSettingsEditor/CommonResources.xaml new file mode 100644 index 000000000..e8c07354d --- /dev/null +++ b/src/cascadia/TerminalSettingsEditor/CommonResources.xaml @@ -0,0 +1,109 @@ + + + 15.0 + 20,0,0,0 + 300 + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/src/cascadia/TerminalSettingsEditor/EnumEntry.h b/src/cascadia/TerminalSettingsEditor/EnumEntry.h new file mode 100644 index 000000000..c625d60b7 --- /dev/null +++ b/src/cascadia/TerminalSettingsEditor/EnumEntry.h @@ -0,0 +1,35 @@ +/*++ +Copyright (c) Microsoft Corporation +Licensed under the MIT license. + +Module Name: +- EnumEntry.h + +Abstract: +- An EnumEntry is intended to be used as a ViewModel for settings + that are an enum value. It holds an enum name and enum value + so that any data binding can easily associate one with the other. + +Author(s): +- Leon Liang - October 2020 + +--*/ +#pragma once + +#include "EnumEntry.g.h" +#include "Utils.h" + +namespace winrt::Microsoft::Terminal::Settings::Editor::implementation +{ + struct EnumEntry : EnumEntryT + { + public: + EnumEntry(const winrt::hstring enumName, const winrt::Windows::Foundation::IInspectable& enumValue) : + _EnumName{ enumName }, + _EnumValue{ enumValue } {} + + WINRT_CALLBACK(PropertyChanged, Windows::UI::Xaml::Data::PropertyChangedEventHandler); + OBSERVABLE_GETSET_PROPERTY(winrt::hstring, EnumName, _PropertyChangedHandlers); + OBSERVABLE_GETSET_PROPERTY(winrt::Windows::Foundation::IInspectable, EnumValue, _PropertyChangedHandlers); + }; +} diff --git a/src/cascadia/TerminalSettingsEditor/EnumEntry.idl b/src/cascadia/TerminalSettingsEditor/EnumEntry.idl new file mode 100644 index 000000000..4b7805137 --- /dev/null +++ b/src/cascadia/TerminalSettingsEditor/EnumEntry.idl @@ -0,0 +1,11 @@ +// Copyright (c) Microsoft Corporation. +// Licensed under the MIT license. + +namespace Microsoft.Terminal.Settings.Editor +{ + [default_interface] runtimeclass EnumEntry : Windows.UI.Xaml.Data.INotifyPropertyChanged + { + String EnumName { get; }; + IInspectable EnumValue { get; }; + } +} diff --git a/src/cascadia/TerminalSettingsEditor/FontWeightConverter.cpp b/src/cascadia/TerminalSettingsEditor/FontWeightConverter.cpp new file mode 100644 index 000000000..5b39eded1 --- /dev/null +++ b/src/cascadia/TerminalSettingsEditor/FontWeightConverter.cpp @@ -0,0 +1,32 @@ +// Copyright (c) Microsoft Corporation. +// Licensed under the MIT license. + +#include "pch.h" +#include "FontWeightConverter.h" +#include "FontWeightConverter.g.cpp" + +using namespace winrt::Windows; +using namespace winrt::Windows::UI::Xaml; +using namespace winrt::Windows::UI::Text; + +namespace winrt::Microsoft::Terminal::Settings::Editor::implementation +{ + Foundation::IInspectable FontWeightConverter::Convert(Foundation::IInspectable const& value, + Windows::UI::Xaml::Interop::TypeName const& /* targetType */, + Foundation::IInspectable const& /* parameter */, + hstring const& /* language */) + { + const auto weight{ winrt::unbox_value(value) }; + return winrt::box_value(weight.Weight); + } + + Foundation::IInspectable FontWeightConverter::ConvertBack(Foundation::IInspectable const& value, + Windows::UI::Xaml::Interop::TypeName const& /* targetType */, + Foundation::IInspectable const& /*parameter*/, + hstring const& /* language */) + { + const auto sliderVal{ winrt::unbox_value(value) }; + FontWeight weight{ base::ClampedNumeric(sliderVal) }; + return winrt::box_value(weight); + } +} diff --git a/src/cascadia/TerminalSettingsEditor/FontWeightConverter.h b/src/cascadia/TerminalSettingsEditor/FontWeightConverter.h new file mode 100644 index 000000000..249e7987d --- /dev/null +++ b/src/cascadia/TerminalSettingsEditor/FontWeightConverter.h @@ -0,0 +1,30 @@ +// Copyright (c) Microsoft Corporation. +// Licensed under the MIT license. + +#pragma once + +#include "FontWeightConverter.g.h" +#include "Utils.h" + +namespace winrt::Microsoft::Terminal::Settings::Editor::implementation +{ + struct FontWeightConverter : FontWeightConverterT + { + FontWeightConverter() = default; + + Windows::Foundation::IInspectable Convert(Windows::Foundation::IInspectable const& value, + Windows::UI::Xaml::Interop::TypeName const& targetType, + Windows::Foundation::IInspectable const& parameter, + hstring const& language); + + Windows::Foundation::IInspectable ConvertBack(Windows::Foundation::IInspectable const& value, + Windows::UI::Xaml::Interop::TypeName const& targetType, + Windows::Foundation::IInspectable const& parameter, + hstring const& language); + }; +} + +namespace winrt::Microsoft::Terminal::Settings::Editor::factory_implementation +{ + BASIC_FACTORY(FontWeightConverter); +} diff --git a/src/cascadia/TerminalSettingsEditor/FontWeightConverter.idl b/src/cascadia/TerminalSettingsEditor/FontWeightConverter.idl new file mode 100644 index 000000000..881c9104f --- /dev/null +++ b/src/cascadia/TerminalSettingsEditor/FontWeightConverter.idl @@ -0,0 +1,10 @@ +// Copyright (c) Microsoft Corporation. +// Licensed under the MIT license. + +namespace Microsoft.Terminal.Settings.Editor +{ + runtimeclass FontWeightConverter : [default] Windows.UI.Xaml.Data.IValueConverter + { + FontWeightConverter(); + }; +} diff --git a/src/cascadia/TerminalSettingsEditor/GlobalAppearance.cpp b/src/cascadia/TerminalSettingsEditor/GlobalAppearance.cpp new file mode 100644 index 000000000..7556dc067 --- /dev/null +++ b/src/cascadia/TerminalSettingsEditor/GlobalAppearance.cpp @@ -0,0 +1,31 @@ +// Copyright (c) Microsoft Corporation. +// Licensed under the MIT license. + +#include "pch.h" +#include "GlobalAppearance.h" +#include "GlobalAppearance.g.cpp" +#include "GlobalAppearancePageNavigationState.g.cpp" +#include "EnumEntry.h" + +using namespace winrt; +using namespace winrt::Windows::UI::Xaml; +using namespace winrt::Windows::UI::Xaml::Navigation; +using namespace winrt::Windows::UI::Xaml::Controls; +using namespace winrt::Microsoft::Terminal::Settings::Model; +using namespace winrt::Windows::Foundation::Collections; + +namespace winrt::Microsoft::Terminal::Settings::Editor::implementation +{ + GlobalAppearance::GlobalAppearance() + { + InitializeComponent(); + + INITIALIZE_BINDABLE_ENUM_SETTING(Theme, ElementTheme, winrt::Windows::UI::Xaml::ElementTheme, L"Globals_Theme", L"Content"); + INITIALIZE_BINDABLE_ENUM_SETTING(TabWidthMode, TabViewWidthMode, winrt::Microsoft::UI::Xaml::Controls::TabViewWidthMode, L"Globals_TabWidthMode", L"Content"); + } + + void GlobalAppearance::OnNavigatedTo(const NavigationEventArgs& e) + { + _State = e.Parameter().as(); + } +} diff --git a/src/cascadia/TerminalSettingsEditor/GlobalAppearance.h b/src/cascadia/TerminalSettingsEditor/GlobalAppearance.h new file mode 100644 index 000000000..eef004bc5 --- /dev/null +++ b/src/cascadia/TerminalSettingsEditor/GlobalAppearance.h @@ -0,0 +1,38 @@ +// Copyright (c) Microsoft Corporation. +// Licensed under the MIT license. + +#pragma once + +#include "GlobalAppearance.g.h" +#include "GlobalAppearancePageNavigationState.g.h" +#include "Utils.h" + +namespace winrt::Microsoft::Terminal::Settings::Editor::implementation +{ + struct GlobalAppearancePageNavigationState : GlobalAppearancePageNavigationStateT + { + public: + GlobalAppearancePageNavigationState(const Model::GlobalAppSettings& settings) : + _Globals{ settings } {} + + GETSET_PROPERTY(Model::GlobalAppSettings, Globals, nullptr) + }; + + struct GlobalAppearance : GlobalAppearanceT + { + public: + GlobalAppearance(); + + void OnNavigatedTo(const winrt::Windows::UI::Xaml::Navigation::NavigationEventArgs& e); + + GETSET_PROPERTY(Editor::GlobalAppearancePageNavigationState, State, nullptr); + + GETSET_BINDABLE_ENUM_SETTING(Theme, winrt::Windows::UI::Xaml::ElementTheme, State().Globals, Theme); + GETSET_BINDABLE_ENUM_SETTING(TabWidthMode, winrt::Microsoft::UI::Xaml::Controls::TabViewWidthMode, State().Globals, TabWidthMode); + }; +} + +namespace winrt::Microsoft::Terminal::Settings::Editor::factory_implementation +{ + BASIC_FACTORY(GlobalAppearance); +} diff --git a/src/cascadia/TerminalSettingsEditor/GlobalAppearance.idl b/src/cascadia/TerminalSettingsEditor/GlobalAppearance.idl new file mode 100644 index 000000000..294f73022 --- /dev/null +++ b/src/cascadia/TerminalSettingsEditor/GlobalAppearance.idl @@ -0,0 +1,24 @@ +// Copyright (c) Microsoft Corporation. +// Licensed under the MIT license. + +import "EnumEntry.idl"; + +namespace Microsoft.Terminal.Settings.Editor +{ + runtimeclass GlobalAppearancePageNavigationState + { + Microsoft.Terminal.Settings.Model.GlobalAppSettings Globals; + }; + + [default_interface] runtimeclass GlobalAppearance : Windows.UI.Xaml.Controls.Page + { + GlobalAppearance(); + GlobalAppearancePageNavigationState State { get; }; + + IInspectable CurrentTheme; + Windows.Foundation.Collections.IObservableVector ThemeList { get; }; + + IInspectable CurrentTabWidthMode; + Windows.Foundation.Collections.IObservableVector TabWidthModeList { get; }; + } +} diff --git a/src/cascadia/TerminalSettingsEditor/GlobalAppearance.xaml b/src/cascadia/TerminalSettingsEditor/GlobalAppearance.xaml new file mode 100644 index 000000000..3b8697155 --- /dev/null +++ b/src/cascadia/TerminalSettingsEditor/GlobalAppearance.xaml @@ -0,0 +1,82 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/src/cascadia/TerminalSettingsEditor/Interaction.cpp b/src/cascadia/TerminalSettingsEditor/Interaction.cpp new file mode 100644 index 000000000..0de5cd3f9 --- /dev/null +++ b/src/cascadia/TerminalSettingsEditor/Interaction.cpp @@ -0,0 +1,22 @@ +// Copyright (c) Microsoft Corporation. +// Licensed under the MIT license. + +#include "pch.h" +#include "Interaction.h" +#include "Interaction.g.cpp" +#include "InteractionPageNavigationState.g.cpp" + +using namespace winrt::Windows::UI::Xaml::Navigation; + +namespace winrt::Microsoft::Terminal::Settings::Editor::implementation +{ + Interaction::Interaction() + { + InitializeComponent(); + } + + void Interaction::OnNavigatedTo(const NavigationEventArgs& e) + { + _State = e.Parameter().as(); + } +} diff --git a/src/cascadia/TerminalSettingsEditor/Interaction.h b/src/cascadia/TerminalSettingsEditor/Interaction.h new file mode 100644 index 000000000..dbfcd7be5 --- /dev/null +++ b/src/cascadia/TerminalSettingsEditor/Interaction.h @@ -0,0 +1,34 @@ +// Copyright (c) Microsoft Corporation. +// Licensed under the MIT license. + +#pragma once + +#include "Interaction.g.h" +#include "InteractionPageNavigationState.g.h" +#include "Utils.h" + +namespace winrt::Microsoft::Terminal::Settings::Editor::implementation +{ + struct InteractionPageNavigationState : InteractionPageNavigationStateT + { + public: + InteractionPageNavigationState(const Model::GlobalAppSettings& settings) : + _Globals{ settings } {} + + GETSET_PROPERTY(Model::GlobalAppSettings, Globals, nullptr) + }; + + struct Interaction : InteractionT + { + Interaction(); + + void OnNavigatedTo(const winrt::Windows::UI::Xaml::Navigation::NavigationEventArgs& e); + + GETSET_PROPERTY(Editor::InteractionPageNavigationState, State, nullptr); + }; +} + +namespace winrt::Microsoft::Terminal::Settings::Editor::factory_implementation +{ + BASIC_FACTORY(Interaction); +} diff --git a/src/cascadia/TerminalSettingsEditor/Interaction.idl b/src/cascadia/TerminalSettingsEditor/Interaction.idl new file mode 100644 index 000000000..a1e63db36 --- /dev/null +++ b/src/cascadia/TerminalSettingsEditor/Interaction.idl @@ -0,0 +1,16 @@ +// Copyright (c) Microsoft Corporation. +// Licensed under the MIT license. + +namespace Microsoft.Terminal.Settings.Editor +{ + runtimeclass InteractionPageNavigationState + { + Microsoft.Terminal.Settings.Model.GlobalAppSettings Globals; + }; + + [default_interface] runtimeclass Interaction : Windows.UI.Xaml.Controls.Page + { + Interaction(); + InteractionPageNavigationState State { get; }; + } +} diff --git a/src/cascadia/TerminalSettingsEditor/Interaction.xaml b/src/cascadia/TerminalSettingsEditor/Interaction.xaml new file mode 100644 index 000000000..eb6bd08e6 --- /dev/null +++ b/src/cascadia/TerminalSettingsEditor/Interaction.xaml @@ -0,0 +1,43 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/src/cascadia/TerminalSettingsEditor/Launch.cpp b/src/cascadia/TerminalSettingsEditor/Launch.cpp new file mode 100644 index 000000000..f1b42c9b0 --- /dev/null +++ b/src/cascadia/TerminalSettingsEditor/Launch.cpp @@ -0,0 +1,39 @@ +// Copyright (c) Microsoft Corporation. +// Licensed under the MIT license. + +#include "pch.h" +#include "Launch.h" +#include "Launch.g.cpp" +#include "LaunchPageNavigationState.g.cpp" +#include "EnumEntry.h" + +using namespace winrt::Windows::UI::Xaml::Navigation; +using namespace winrt::Windows::Foundation; +using namespace winrt::Microsoft::Terminal::Settings::Model; + +namespace winrt::Microsoft::Terminal::Settings::Editor::implementation +{ + Launch::Launch() + { + InitializeComponent(); + + INITIALIZE_BINDABLE_ENUM_SETTING(LaunchMode, LaunchMode, LaunchMode, L"Globals_LaunchMode", L"Content"); + } + + void Launch::OnNavigatedTo(const NavigationEventArgs& e) + { + _State = e.Parameter().as(); + } + + IInspectable Launch::CurrentDefaultProfile() + { + const auto defaultProfileGuid{ _State.Settings().GlobalSettings().DefaultProfile() }; + return winrt::box_value(_State.Settings().FindProfile(defaultProfileGuid)); + } + + void Launch::CurrentDefaultProfile(const IInspectable& value) + { + const auto profile{ winrt::unbox_value(value) }; + _State.Settings().GlobalSettings().DefaultProfile(profile.Guid()); + } +} diff --git a/src/cascadia/TerminalSettingsEditor/Launch.h b/src/cascadia/TerminalSettingsEditor/Launch.h new file mode 100644 index 000000000..0cede6a9f --- /dev/null +++ b/src/cascadia/TerminalSettingsEditor/Launch.h @@ -0,0 +1,40 @@ +// Copyright (c) Microsoft Corporation. +// Licensed under the MIT license. + +#pragma once + +#include "Launch.g.h" +#include "LaunchPageNavigationState.g.h" +#include "Utils.h" + +namespace winrt::Microsoft::Terminal::Settings::Editor::implementation +{ + struct LaunchPageNavigationState : LaunchPageNavigationStateT + { + public: + LaunchPageNavigationState(const Model::CascadiaSettings& settings) : + _Settings{ settings } {} + + GETSET_PROPERTY(Model::CascadiaSettings, Settings, nullptr) + }; + + struct Launch : LaunchT + { + public: + Launch(); + + void OnNavigatedTo(const winrt::Windows::UI::Xaml::Navigation::NavigationEventArgs& e); + + IInspectable CurrentDefaultProfile(); + void CurrentDefaultProfile(const IInspectable& value); + + GETSET_PROPERTY(Editor::LaunchPageNavigationState, State, nullptr); + + GETSET_BINDABLE_ENUM_SETTING(LaunchMode, Model::LaunchMode, State().Settings().GlobalSettings, LaunchMode); + }; +} + +namespace winrt::Microsoft::Terminal::Settings::Editor::factory_implementation +{ + BASIC_FACTORY(Launch); +} diff --git a/src/cascadia/TerminalSettingsEditor/Launch.idl b/src/cascadia/TerminalSettingsEditor/Launch.idl new file mode 100644 index 000000000..8823a80fb --- /dev/null +++ b/src/cascadia/TerminalSettingsEditor/Launch.idl @@ -0,0 +1,23 @@ +// Copyright (c) Microsoft Corporation. +// Licensed under the MIT license. + +import "EnumEntry.idl"; + +namespace Microsoft.Terminal.Settings.Editor +{ + runtimeclass LaunchPageNavigationState + { + Microsoft.Terminal.Settings.Model.CascadiaSettings Settings; + }; + + [default_interface] runtimeclass Launch : Windows.UI.Xaml.Controls.Page + { + Launch(); + LaunchPageNavigationState State { get; }; + + IInspectable CurrentDefaultProfile; + + IInspectable CurrentLaunchMode; + Windows.Foundation.Collections.IObservableVector LaunchModeList { get; }; + } +} diff --git a/src/cascadia/TerminalSettingsEditor/Launch.xaml b/src/cascadia/TerminalSettingsEditor/Launch.xaml new file mode 100644 index 000000000..4e04f78eb --- /dev/null +++ b/src/cascadia/TerminalSettingsEditor/Launch.xaml @@ -0,0 +1,131 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/src/cascadia/TerminalSettingsEditor/MainPage.cpp b/src/cascadia/TerminalSettingsEditor/MainPage.cpp new file mode 100644 index 000000000..4d4a19adf --- /dev/null +++ b/src/cascadia/TerminalSettingsEditor/MainPage.cpp @@ -0,0 +1,316 @@ +// Copyright (c) Microsoft Corporation. +// Licensed under the MIT license. + +#include "pch.h" +#include "MainPage.h" +#include "MainPage.g.cpp" +#include "Launch.h" +#include "Interaction.h" +#include "Rendering.h" +#include "Profiles.h" +#include "GlobalAppearance.h" +#include "ColorSchemes.h" + +#include + +namespace winrt +{ + namespace MUX = Microsoft::UI::Xaml; + namespace WUX = Windows::UI::Xaml; +} + +using namespace winrt::Windows::Foundation; +using namespace winrt::Windows::UI::Xaml; +using namespace winrt::Microsoft::Terminal::Settings::Model; +using namespace winrt::Windows::UI::Core; +using namespace winrt::Windows::System; +using namespace winrt::Windows::UI::Xaml::Controls; + +static const std::wstring_view launchTag{ L"Launch_Nav" }; +static const std::wstring_view interactionTag{ L"Interaction_Nav" }; +static const std::wstring_view renderingTag{ L"Rendering_Nav" }; +static const std::wstring_view globalProfileTag{ L"GlobalProfile_Nav" }; +static const std::wstring_view addProfileTag{ L"AddProfile" }; +static const std::wstring_view colorSchemesTag{ L"ColorSchemes_Nav" }; +static const std::wstring_view globalAppearanceTag{ L"GlobalAppearance_Nav" }; + +namespace winrt::Microsoft::Terminal::Settings::Editor::implementation +{ + static Editor::ProfileViewModel _viewModelForProfile(const Model::Profile& profile) + { + return winrt::make(profile); + } + + MainPage::MainPage(const CascadiaSettings& settings) : + _settingsSource{ settings }, + _settingsClone{ settings.Copy() } + { + InitializeComponent(); + + _InitializeProfilesList(); + } + + // Method Description: + // - Update the Settings UI with a new CascadiaSettings to bind to + // Arguments: + // - settings - the new settings source + // Return value: + // - + fire_and_forget MainPage::UpdateSettings(Model::CascadiaSettings settings) + { + _settingsSource = settings; + _settingsClone = settings.Copy(); + + co_await winrt::resume_foreground(Dispatcher()); + + // "remove" all profile-related NavViewItems + // LOAD-BEARING: use Visibility here, instead of menuItems.Remove(). + // Remove() works fine on NavViewItems with an hstring tag, + // but causes an out-of-bounds error with Profile tagged items. + // The cause of this error is unknown. + auto menuItems{ SettingsNav().MenuItems() }; + for (auto i = menuItems.Size() - 1; i > 0; --i) + { + if (const auto navViewItem{ menuItems.GetAt(i).try_as() }) + { + if (const auto tag{ navViewItem.Tag() }) + { + if (tag.try_as()) + { + // hide NavViewItem pointing to a Profile + navViewItem.Visibility(Visibility::Collapsed); + } + else if (const auto stringTag{ tag.try_as() }) + { + if (stringTag == addProfileTag) + { + // hide NavViewItem pointing to "Add Profile" + navViewItem.Visibility(Visibility::Collapsed); + } + } + } + } + } + _InitializeProfilesList(); + + _RefreshCurrentPage(); + } + + void MainPage::_RefreshCurrentPage() + { + auto navigationMenu{ SettingsNav() }; + if (const auto selectedItem{ navigationMenu.SelectedItem() }) + { + if (const auto tag{ selectedItem.as().Tag() }) + { + if (const auto profile{ tag.try_as() }) + { + // check if the profile still exists + if (_settingsClone.FindProfile(profile.Guid())) + { + // Navigate to the page with the given profile + contentFrame().Navigate(xaml_typename(), winrt::make(_viewModelForProfile(profile), _settingsClone.GlobalSettings().ColorSchemes(), *this)); + return; + } + } + else if (const auto stringTag{ tag.try_as() }) + { + // navigate to the page with this tag + _Navigate(*stringTag); + return; + } + } + } + + // could not find the page we were on, fallback to first menu item + const auto firstItem{ navigationMenu.MenuItems().GetAt(0) }; + navigationMenu.SelectedItem(firstItem); + if (const auto tag{ navigationMenu.SelectedItem().as().Tag() }) + { + _Navigate(unbox_value(tag)); + } + } + + void MainPage::SetHostingWindow(uint64_t hostingWindow) noexcept + { + _hostingHwnd.emplace(reinterpret_cast(hostingWindow)); + } + + bool MainPage::TryPropagateHostingWindow(IInspectable object) noexcept + { + if (_hostingHwnd) + { + if (auto initializeWithWindow{ object.try_as() }) + { + return SUCCEEDED(initializeWithWindow->Initialize(*_hostingHwnd)); + } + } + return false; + } + + // Function Description: + // - Called when the NavigationView is loaded. Navigates to the first item in the NavigationView, if no item is selected + // Arguments: + // - + // Return Value: + // - + void MainPage::SettingsNav_Loaded(IInspectable const&, RoutedEventArgs const&) + { + if (SettingsNav().SelectedItem() == nullptr) + { + const auto initialItem = SettingsNav().MenuItems().GetAt(0); + SettingsNav().SelectedItem(initialItem); + + // Manually navigate because setting the selected item programmatically doesn't trigger ItemInvoked. + if (const auto tag = initialItem.as().Tag()) + { + _Navigate(unbox_value(tag)); + } + } + } + + // Function Description: + // - Called when NavigationView items are invoked. Navigates to the corresponding page. + // Arguments: + // - args - additional event info from invoking the NavViewItem + // Return Value: + // - + void MainPage::SettingsNav_ItemInvoked(MUX::Controls::NavigationView const&, MUX::Controls::NavigationViewItemInvokedEventArgs const& args) + { + if (const auto clickedItemContainer = args.InvokedItemContainer()) + { + if (const auto navString = clickedItemContainer.Tag().try_as()) + { + if (navString == addProfileTag) + { + // "AddProfile" needs to create a new profile before we can navigate to it + uint32_t insertIndex; + SettingsNav().MenuItems().IndexOf(clickedItemContainer, insertIndex); + _CreateAndNavigateToNewProfile(insertIndex); + } + else + { + // Otherwise, navigate to the page + _Navigate(*navString); + } + } + else if (const auto profile = clickedItemContainer.Tag().try_as()) + { + // Navigate to a page with the given profile + contentFrame().Navigate(xaml_typename(), winrt::make(profile, _settingsClone.GlobalSettings().ColorSchemes(), *this)); + } + } + } + + void MainPage::_Navigate(hstring clickedItemTag) + { + if (clickedItemTag == launchTag) + { + contentFrame().Navigate(xaml_typename(), winrt::make(_settingsClone)); + } + else if (clickedItemTag == interactionTag) + { + contentFrame().Navigate(xaml_typename(), winrt::make(_settingsClone.GlobalSettings())); + } + else if (clickedItemTag == renderingTag) + { + contentFrame().Navigate(xaml_typename(), winrt::make(_settingsClone.GlobalSettings())); + } + else if (clickedItemTag == globalProfileTag) + { + contentFrame().Navigate(xaml_typename(), winrt::make(_viewModelForProfile(_settingsClone.ProfileDefaults()), _settingsClone.GlobalSettings().ColorSchemes(), *this)); + } + else if (clickedItemTag == colorSchemesTag) + { + contentFrame().Navigate(xaml_typename(), winrt::make(_settingsClone.GlobalSettings())); + } + else if (clickedItemTag == globalAppearanceTag) + { + contentFrame().Navigate(xaml_typename(), winrt::make(_settingsClone.GlobalSettings())); + } + } + + void MainPage::OpenJsonTapped(IInspectable const& /*sender*/, Windows::UI::Xaml::Input::TappedRoutedEventArgs const& /*args*/) + { + const CoreWindow window = CoreWindow::GetForCurrentThread(); + const auto rAltState = window.GetKeyState(VirtualKey::RightMenu); + const auto lAltState = window.GetKeyState(VirtualKey::LeftMenu); + const bool altPressed = WI_IsFlagSet(lAltState, CoreVirtualKeyStates::Down) || + WI_IsFlagSet(rAltState, CoreVirtualKeyStates::Down); + + const auto target = altPressed ? SettingsTarget::DefaultsFile : SettingsTarget::SettingsFile; + _OpenJsonHandlers(nullptr, target); + } + + void MainPage::OpenJsonKeyDown(IInspectable const& /*sender*/, Windows::UI::Xaml::Input::KeyRoutedEventArgs const& args) + { + if (args.Key() == VirtualKey::Enter || args.Key() == VirtualKey::Space) + { + const auto target = args.KeyStatus().IsMenuKeyDown ? SettingsTarget::DefaultsFile : SettingsTarget::SettingsFile; + _OpenJsonHandlers(nullptr, target); + } + } + + void MainPage::SaveButton_Click(IInspectable const& /*sender*/, RoutedEventArgs const& /*args*/) + { + _settingsClone.WriteSettingsToDisk(); + } + + void MainPage::ResetButton_Click(IInspectable const& /*sender*/, RoutedEventArgs const& /*args*/) + { + _settingsClone = _settingsSource.Copy(); + _RefreshCurrentPage(); + } + + void MainPage::_InitializeProfilesList() + { + // Manually create a NavigationViewItem for each profile + // and keep a reference to them in a map so that we + // can easily modify the correct one when the associated + // profile changes. + for (const auto& profile : _settingsClone.AllProfiles()) + { + auto navItem = _CreateProfileNavViewItem(_viewModelForProfile(profile)); + SettingsNav().MenuItems().Append(navItem); + } + + // Top off (the end of the nav view) with the Add Profile item + MUX::Controls::NavigationViewItem addProfileItem; + addProfileItem.Content(box_value(RS_(L"Nav_AddNewProfile/Content"))); + addProfileItem.Tag(box_value(addProfileTag)); + addProfileItem.SelectsOnInvoked(false); + + FontIcon icon; + // This is the "Add" symbol + icon.Glyph(L"\xE710"); + addProfileItem.Icon(icon); + + SettingsNav().MenuItems().Append(addProfileItem); + } + + void MainPage::_CreateAndNavigateToNewProfile(const uint32_t index) + { + const auto newProfile{ _settingsClone.CreateNewProfile() }; + const auto profileViewModel{ _viewModelForProfile(newProfile) }; + const auto navItem{ _CreateProfileNavViewItem(profileViewModel) }; + SettingsNav().MenuItems().InsertAt(index, navItem); + + // Select and navigate to the new profile + SettingsNav().SelectedItem(navItem); + contentFrame().Navigate(xaml_typename(), winrt::make(profileViewModel, _settingsClone.GlobalSettings().ColorSchemes(), *this)); + } + + MUX::Controls::NavigationViewItem MainPage::_CreateProfileNavViewItem(const Editor::ProfileViewModel& profile) + { + MUX::Controls::NavigationViewItem profileNavItem; + profileNavItem.Content(box_value(profile.Name())); + profileNavItem.Tag(box_value(profile)); + + const auto iconSource{ IconPathConverter::IconSourceWUX(profile.Icon()) }; + WUX::Controls::IconSourceElement icon; + icon.IconSource(iconSource); + profileNavItem.Icon(icon); + + return profileNavItem; + } +} diff --git a/src/cascadia/TerminalSettingsEditor/MainPage.h b/src/cascadia/TerminalSettingsEditor/MainPage.h new file mode 100644 index 000000000..21217987d --- /dev/null +++ b/src/cascadia/TerminalSettingsEditor/MainPage.h @@ -0,0 +1,48 @@ +// Copyright (c) Microsoft Corporation. +// Licensed under the MIT license. + +#pragma once + +#include "MainPage.g.h" +#include "Utils.h" + +namespace winrt::Microsoft::Terminal::Settings::Editor::implementation +{ + struct MainPage : MainPageT + { + MainPage() = delete; + MainPage(const Model::CascadiaSettings& settings); + + fire_and_forget UpdateSettings(Model::CascadiaSettings settings); + + void OpenJsonKeyDown(Windows::Foundation::IInspectable const& sender, Windows::UI::Xaml::Input::KeyRoutedEventArgs const& args); + void OpenJsonTapped(Windows::Foundation::IInspectable const& sender, Windows::UI::Xaml::Input::TappedRoutedEventArgs const& args); + void SettingsNav_Loaded(Windows::Foundation::IInspectable const& sender, Windows::UI::Xaml::RoutedEventArgs const& args); + void SettingsNav_ItemInvoked(Microsoft::UI::Xaml::Controls::NavigationView const& sender, Microsoft::UI::Xaml::Controls::NavigationViewItemInvokedEventArgs const& args); + void SaveButton_Click(Windows::Foundation::IInspectable const& sender, Windows::UI::Xaml::RoutedEventArgs const& args); + void ResetButton_Click(Windows::Foundation::IInspectable const& sender, Windows::UI::Xaml::RoutedEventArgs const& args); + + void SetHostingWindow(uint64_t hostingWindow) noexcept; + bool TryPropagateHostingWindow(IInspectable object) noexcept; + + TYPED_EVENT(OpenJson, Windows::Foundation::IInspectable, Model::SettingsTarget); + + private: + Model::CascadiaSettings _settingsSource; + Model::CascadiaSettings _settingsClone; + + std::optional _hostingHwnd; + + void _InitializeProfilesList(); + void _CreateAndNavigateToNewProfile(const uint32_t index); + winrt::Microsoft::UI::Xaml::Controls::NavigationViewItem _CreateProfileNavViewItem(const ProfileViewModel& profile); + + void _Navigate(hstring clickedItemTag); + void _RefreshCurrentPage(); + }; +} + +namespace winrt::Microsoft::Terminal::Settings::Editor::factory_implementation +{ + BASIC_FACTORY(MainPage); +} diff --git a/src/cascadia/TerminalSettingsEditor/MainPage.idl b/src/cascadia/TerminalSettingsEditor/MainPage.idl new file mode 100644 index 000000000..cd35a8aa2 --- /dev/null +++ b/src/cascadia/TerminalSettingsEditor/MainPage.idl @@ -0,0 +1,26 @@ +// Copyright (c) Microsoft Corporation. +// Licensed under the MIT license. + +namespace Microsoft.Terminal.Settings.Editor +{ + // Due to a XAML Compiler bug, it is hard for us to propagate an HWND into a XAML-using runtimeclass. + // To work around that, we'll only propagate the HWND (when we need to) into the settings' toplevel page + // and use IHostedInWindow to hide the implementation detail where we use IInitializeWithWindow (shobjidl_core) + // https://github.com/microsoft/microsoft-ui-xaml/issues/3331 + interface IHostedInWindow + { + Boolean TryPropagateHostingWindow(IInspectable i); + } + + [default_interface] runtimeclass MainPage : Windows.UI.Xaml.Controls.Page, IHostedInWindow + { + MainPage(Microsoft.Terminal.Settings.Model.CascadiaSettings settings); + + void UpdateSettings(Microsoft.Terminal.Settings.Model.CascadiaSettings settings); + event Windows.Foundation.TypedEventHandler OpenJson; + + // Due to the aforementioned bug, we can't use IInitializeWithWindow _here_ either. + // Let's just smuggle the HWND in as a UInt64 :| + void SetHostingWindow(UInt64 window); + } +} diff --git a/src/cascadia/TerminalSettingsEditor/MainPage.xaml b/src/cascadia/TerminalSettingsEditor/MainPage.xaml new file mode 100644 index 000000000..85c269eae --- /dev/null +++ b/src/cascadia/TerminalSettingsEditor/MainPage.xaml @@ -0,0 +1,142 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +