mirror of
https://github.com/microsoft/terminal.git
synced 2026-02-04 05:35:20 +00:00
Apply MVVM for profiles in SUI (#11877)
## Summary of the Pull Request Cleans up `ProfileViewModel`, `Profiles`, and `ProfilePageNavigationState` to move all of the view model responsibilities over to `ProfileViewModel`. We don't actually store the `ProfilePageNavigationState` anymore. We only use it as a way to transfer information to the new page. ## References #9207 - Apply MVVM ## Detailed Description of the Pull Request / Additional comments - I pulled out `ProfileViewModel` into its own file to keep things cleaner. It was getting pretty big. - The font lists are now stored in a static location in `ProfileViewModel`, which means that we can reuse the same list between pages. - the profile pivot was also moved to the `ProfileViewModel` and stored as a static value. ## Validation Steps Performed ✅ pivot behavior is the same ✅ font list is still populated
This commit is contained in:
@@ -142,7 +142,7 @@ namespace winrt::Microsoft::Terminal::Settings::Editor::implementation
|
||||
{
|
||||
bool result{ false };
|
||||
const auto currentFont{ Appearance().FontFace() };
|
||||
for (const auto& font : SourceProfile().MonospaceFontList())
|
||||
for (const auto& font : ProfileViewModel::MonospaceFontList())
|
||||
{
|
||||
if (font.LocalizedName() == currentFont)
|
||||
{
|
||||
@@ -175,7 +175,7 @@ namespace winrt::Microsoft::Terminal::Settings::Editor::implementation
|
||||
// look for the current font in our shown list of fonts
|
||||
const auto& appearanceVM{ Appearance() };
|
||||
const auto appearanceFontFace{ appearanceVM.FontFace() };
|
||||
const auto& currentFontList{ ShowAllFonts() ? SourceProfile().CompleteFontList() : SourceProfile().MonospaceFontList() };
|
||||
const auto& currentFontList{ ShowAllFonts() ? ProfileViewModel::CompleteFontList() : ProfileViewModel::MonospaceFontList() };
|
||||
IInspectable fallbackFont;
|
||||
for (const auto& font : currentFontList)
|
||||
{
|
||||
|
||||
@@ -129,16 +129,16 @@ namespace winrt::Microsoft::Terminal::Settings::Editor::implementation
|
||||
bool IsCustomFontWeight();
|
||||
WINRT_PROPERTY(Windows::Foundation::Collections::IObservableVector<Microsoft::Terminal::Settings::Editor::EnumEntry>, FontWeightList);
|
||||
|
||||
GETSET_BINDABLE_ENUM_SETTING(CursorShape, Microsoft::Terminal::Core::CursorStyle, Appearance, CursorShape);
|
||||
GETSET_BINDABLE_ENUM_SETTING(CursorShape, Microsoft::Terminal::Core::CursorStyle, Appearance(), CursorShape);
|
||||
WINRT_PROPERTY(Windows::Foundation::Collections::IObservableVector<Model::ColorScheme>, ColorSchemeList, nullptr);
|
||||
|
||||
WINRT_CALLBACK(PropertyChanged, Windows::UI::Xaml::Data::PropertyChangedEventHandler);
|
||||
DEPENDENCY_PROPERTY(Editor::AppearanceViewModel, Appearance);
|
||||
WINRT_PROPERTY(Editor::ProfileViewModel, SourceProfile, nullptr);
|
||||
|
||||
GETSET_BINDABLE_ENUM_SETTING(BackgroundImageStretchMode, Windows::UI::Xaml::Media::Stretch, Appearance, BackgroundImageStretchMode);
|
||||
GETSET_BINDABLE_ENUM_SETTING(BackgroundImageStretchMode, Windows::UI::Xaml::Media::Stretch, Appearance(), BackgroundImageStretchMode);
|
||||
|
||||
GETSET_BINDABLE_ENUM_SETTING(IntenseTextStyle, Microsoft::Terminal::Settings::Model::IntenseStyle, Appearance, IntenseTextStyle);
|
||||
GETSET_BINDABLE_ENUM_SETTING(IntenseTextStyle, Microsoft::Terminal::Settings::Model::IntenseStyle, Appearance(), IntenseTextStyle);
|
||||
|
||||
private:
|
||||
bool _ShowAllFonts;
|
||||
|
||||
@@ -28,8 +28,8 @@ namespace winrt::Microsoft::Terminal::Settings::Editor::implementation
|
||||
bool FeatureNotificationIconEnabled() const noexcept;
|
||||
|
||||
WINRT_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);
|
||||
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);
|
||||
|
||||
public:
|
||||
// LanguageDisplayConverter maps the given BCP 47 tag to a localized string.
|
||||
|
||||
@@ -26,8 +26,8 @@ namespace winrt::Microsoft::Terminal::Settings::Editor::implementation
|
||||
|
||||
WINRT_PROPERTY(Editor::InteractionPageNavigationState, State, nullptr);
|
||||
|
||||
GETSET_BINDABLE_ENUM_SETTING(TabSwitcherMode, Model::TabSwitcherMode, State().Globals, TabSwitcherMode);
|
||||
GETSET_BINDABLE_ENUM_SETTING(CopyFormat, winrt::Microsoft::Terminal::Control::CopyFormat, State().Globals, CopyFormatting);
|
||||
GETSET_BINDABLE_ENUM_SETTING(TabSwitcherMode, Model::TabSwitcherMode, State().Globals(), TabSwitcherMode);
|
||||
GETSET_BINDABLE_ENUM_SETTING(CopyFormat, winrt::Microsoft::Terminal::Control::CopyFormat, State().Globals(), CopyFormatting);
|
||||
};
|
||||
}
|
||||
|
||||
|
||||
@@ -33,9 +33,9 @@ namespace winrt::Microsoft::Terminal::Settings::Editor::implementation
|
||||
|
||||
WINRT_PROPERTY(Editor::LaunchPageNavigationState, State, nullptr);
|
||||
|
||||
GETSET_BINDABLE_ENUM_SETTING(FirstWindowPreference, Model::FirstWindowPreference, State().Settings().GlobalSettings, FirstWindowPreference);
|
||||
GETSET_BINDABLE_ENUM_SETTING(LaunchMode, Model::LaunchMode, State().Settings().GlobalSettings, LaunchMode);
|
||||
GETSET_BINDABLE_ENUM_SETTING(WindowingBehavior, Model::WindowingMode, State().Settings().GlobalSettings, WindowingBehavior);
|
||||
GETSET_BINDABLE_ENUM_SETTING(FirstWindowPreference, Model::FirstWindowPreference, State().Settings().GlobalSettings(), FirstWindowPreference);
|
||||
GETSET_BINDABLE_ENUM_SETTING(LaunchMode, Model::LaunchMode, State().Settings().GlobalSettings(), LaunchMode);
|
||||
GETSET_BINDABLE_ENUM_SETTING(WindowingBehavior, Model::WindowingMode, State().Settings().GlobalSettings(), WindowingBehavior);
|
||||
};
|
||||
}
|
||||
|
||||
|
||||
@@ -298,12 +298,11 @@ namespace winrt::Microsoft::Terminal::Settings::Editor::implementation
|
||||
{
|
||||
auto profileVM{ _viewModelForProfile(_settingsClone.ProfileDefaults(), _settingsClone) };
|
||||
profileVM.IsBaseLayer(true);
|
||||
_lastProfilesNavState = winrt::make<ProfilePageNavigationState>(profileVM,
|
||||
_settingsClone.GlobalSettings().ColorSchemes(),
|
||||
_lastProfilesNavState,
|
||||
*this);
|
||||
auto state{ winrt::make<ProfilePageNavigationState>(profileVM,
|
||||
_settingsClone.GlobalSettings().ColorSchemes(),
|
||||
*this) };
|
||||
|
||||
contentFrame().Navigate(xaml_typename<Editor::Profiles>(), _lastProfilesNavState);
|
||||
contentFrame().Navigate(xaml_typename<Editor::Profiles>(), state);
|
||||
}
|
||||
else if (clickedItemTag == colorSchemesTag)
|
||||
{
|
||||
@@ -328,15 +327,14 @@ namespace winrt::Microsoft::Terminal::Settings::Editor::implementation
|
||||
// - profile - the profile object we are getting a view of
|
||||
void MainPage::_Navigate(const Editor::ProfileViewModel& profile)
|
||||
{
|
||||
_lastProfilesNavState = winrt::make<ProfilePageNavigationState>(profile,
|
||||
_settingsClone.GlobalSettings().ColorSchemes(),
|
||||
_lastProfilesNavState,
|
||||
*this);
|
||||
auto state{ winrt::make<ProfilePageNavigationState>(profile,
|
||||
_settingsClone.GlobalSettings().ColorSchemes(),
|
||||
*this) };
|
||||
|
||||
// Add an event handler for when the user wants to delete a profile.
|
||||
_lastProfilesNavState.DeleteProfile({ this, &MainPage::_DeleteProfile });
|
||||
profile.DeleteProfile({ this, &MainPage::_DeleteProfile });
|
||||
|
||||
contentFrame().Navigate(xaml_typename<Editor::Profiles>(), _lastProfilesNavState);
|
||||
contentFrame().Navigate(xaml_typename<Editor::Profiles>(), state);
|
||||
}
|
||||
|
||||
void MainPage::OpenJsonTapped(IInspectable const& /*sender*/, Windows::UI::Xaml::Input::TappedRoutedEventArgs const& /*args*/)
|
||||
|
||||
@@ -46,7 +46,6 @@ namespace winrt::Microsoft::Terminal::Settings::Editor::implementation
|
||||
void _Navigate(const Editor::ProfileViewModel& profile);
|
||||
|
||||
winrt::Microsoft::Terminal::Settings::Editor::ColorSchemesPageNavigationState _colorSchemesNavState{ nullptr };
|
||||
winrt::Microsoft::Terminal::Settings::Editor::ProfilePageNavigationState _lastProfilesNavState{ nullptr };
|
||||
};
|
||||
}
|
||||
|
||||
|
||||
@@ -73,6 +73,10 @@
|
||||
<DependentUpon>Profiles.xaml</DependentUpon>
|
||||
<SubType>Code</SubType>
|
||||
</ClInclude>
|
||||
<ClInclude Include="ProfileViewModel.h">
|
||||
<DependentUpon>ProfileViewModel.idl</DependentUpon>
|
||||
<SubType>Code</SubType>
|
||||
</ClInclude>
|
||||
<ClInclude Include="Appearances.h">
|
||||
<DependentUpon>Appearances.xaml</DependentUpon>
|
||||
<SubType>Code</SubType>
|
||||
@@ -167,6 +171,10 @@
|
||||
<DependentUpon>Profiles.xaml</DependentUpon>
|
||||
<SubType>Code</SubType>
|
||||
</ClCompile>
|
||||
<ClCompile Include="ProfileViewModel.cpp">
|
||||
<DependentUpon>ProfileViewModel.idl</DependentUpon>
|
||||
<SubType>Code</SubType>
|
||||
</ClCompile>
|
||||
<ClCompile Include="Appearances.cpp">
|
||||
<DependentUpon>Appearances.xaml</DependentUpon>
|
||||
<SubType>Code</SubType>
|
||||
@@ -225,6 +233,7 @@
|
||||
<DependentUpon>Profiles.xaml</DependentUpon>
|
||||
<SubType>Code</SubType>
|
||||
</Midl>
|
||||
<Midl Include="ProfileViewModel.idl" />
|
||||
<Midl Include="Appearances.idl">
|
||||
<DependentUpon>Appearances.xaml</DependentUpon>
|
||||
<SubType>Code</SubType>
|
||||
|
||||
@@ -17,6 +17,7 @@
|
||||
<ClInclude Include="PreviewConnection.h" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<Midl Include="ProfileViewModel.idl" />
|
||||
<Midl Include="EnumEntry.idl" />
|
||||
<Midl Include="Converters.idl">
|
||||
<Filter>Converters</Filter>
|
||||
|
||||
417
src/cascadia/TerminalSettingsEditor/ProfileViewModel.cpp
Normal file
417
src/cascadia/TerminalSettingsEditor/ProfileViewModel.cpp
Normal file
@@ -0,0 +1,417 @@
|
||||
// Copyright (c) Microsoft Corporation.
|
||||
// Licensed under the MIT license.
|
||||
|
||||
#include "pch.h"
|
||||
#include "ProfileViewModel.h"
|
||||
#include "ProfileViewModel.g.cpp"
|
||||
#include "EnumEntry.h"
|
||||
|
||||
#include <LibraryResources.h>
|
||||
#include "..\WinRTUtils\inc\Utils.h"
|
||||
|
||||
// This function is a copy of DxFontInfo::_NearbyCollection() with
|
||||
// * the call to DxFontInfo::s_GetNearbyFonts() inlined
|
||||
// * checkForUpdates for GetSystemFontCollection() set to true
|
||||
static wil::com_ptr<IDWriteFontCollection1> NearbyCollection(IDWriteFactory* dwriteFactory)
|
||||
{
|
||||
// The convenience interfaces for loading fonts from files
|
||||
// are only available on Windows 10+.
|
||||
wil::com_ptr<IDWriteFactory6> factory6;
|
||||
// wil's query() facilities don't work inside WinRT land at the moment.
|
||||
// They produce a compilation error due to IUnknown and winrt::Windows::Foundation::IUnknown being ambiguous.
|
||||
if (!SUCCEEDED(dwriteFactory->QueryInterface(__uuidof(IDWriteFactory6), factory6.put_void())))
|
||||
{
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
wil::com_ptr<IDWriteFontCollection1> systemFontCollection;
|
||||
THROW_IF_FAILED(factory6->GetSystemFontCollection(false, systemFontCollection.addressof(), true));
|
||||
|
||||
wil::com_ptr<IDWriteFontSet> systemFontSet;
|
||||
THROW_IF_FAILED(systemFontCollection->GetFontSet(systemFontSet.addressof()));
|
||||
|
||||
wil::com_ptr<IDWriteFontSetBuilder2> fontSetBuilder2;
|
||||
THROW_IF_FAILED(factory6->CreateFontSetBuilder(fontSetBuilder2.addressof()));
|
||||
|
||||
THROW_IF_FAILED(fontSetBuilder2->AddFontSet(systemFontSet.get()));
|
||||
|
||||
{
|
||||
const std::filesystem::path module{ wil::GetModuleFileNameW<std::wstring>(nullptr) };
|
||||
const auto folder{ module.parent_path() };
|
||||
|
||||
for (const auto& p : std::filesystem::directory_iterator(folder))
|
||||
{
|
||||
if (til::ends_with(p.path().native(), L".ttf"))
|
||||
{
|
||||
fontSetBuilder2->AddFontFile(p.path().c_str());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
wil::com_ptr<IDWriteFontSet> fontSet;
|
||||
THROW_IF_FAILED(fontSetBuilder2->CreateFontSet(fontSet.addressof()));
|
||||
|
||||
wil::com_ptr<IDWriteFontCollection1> fontCollection;
|
||||
THROW_IF_FAILED(factory6->CreateFontCollectionFromFontSet(fontSet.get(), &fontCollection));
|
||||
|
||||
return fontCollection;
|
||||
}
|
||||
|
||||
using namespace winrt::Windows::UI::Text;
|
||||
using namespace winrt::Windows::UI::Xaml;
|
||||
using namespace winrt::Windows::UI::Xaml::Controls;
|
||||
using namespace winrt::Windows::UI::Xaml::Data;
|
||||
using namespace winrt::Windows::UI::Xaml::Navigation;
|
||||
using namespace winrt::Windows::Foundation;
|
||||
using namespace winrt::Windows::Foundation::Collections;
|
||||
using namespace winrt::Microsoft::Terminal::Settings::Model;
|
||||
|
||||
namespace winrt::Microsoft::Terminal::Settings::Editor::implementation
|
||||
{
|
||||
Windows::Foundation::Collections::IObservableVector<Editor::Font> ProfileViewModel::_MonospaceFontList{ nullptr };
|
||||
Windows::Foundation::Collections::IObservableVector<Editor::Font> ProfileViewModel::_FontList{ nullptr };
|
||||
ProfilesPivots ProfileViewModel::_LastActivePivot{ ProfilesPivots::General };
|
||||
|
||||
ProfileViewModel::ProfileViewModel(const Model::Profile& profile, const Model::CascadiaSettings& appSettings) :
|
||||
_profile{ profile },
|
||||
_defaultAppearanceViewModel{ winrt::make<implementation::AppearanceViewModel>(profile.DefaultAppearance().try_as<AppearanceConfig>()) },
|
||||
_originalProfileGuid{ profile.Guid() },
|
||||
_appSettings{ appSettings },
|
||||
_unfocusedAppearanceViewModel{ nullptr }
|
||||
{
|
||||
INITIALIZE_BINDABLE_ENUM_SETTING(AntiAliasingMode, TextAntialiasingMode, winrt::Microsoft::Terminal::Control::TextAntialiasingMode, L"Profile_AntialiasingMode", L"Content");
|
||||
INITIALIZE_BINDABLE_ENUM_SETTING_REVERSE_ORDER(CloseOnExitMode, CloseOnExitMode, winrt::Microsoft::Terminal::Settings::Model::CloseOnExitMode, L"Profile_CloseOnExit", L"Content");
|
||||
INITIALIZE_BINDABLE_ENUM_SETTING(ScrollState, ScrollbarState, winrt::Microsoft::Terminal::Control::ScrollbarState, L"Profile_ScrollbarVisibility", L"Content");
|
||||
|
||||
// Add a property changed handler to our own property changed event.
|
||||
// This propagates changes from the settings model to anybody listening to our
|
||||
// unique view model members.
|
||||
PropertyChanged([this](auto&&, const PropertyChangedEventArgs& args) {
|
||||
const auto viewModelProperty{ args.PropertyName() };
|
||||
if (viewModelProperty == L"IsBaseLayer")
|
||||
{
|
||||
// we _always_ want to show the background image settings in base layer
|
||||
_NotifyChanges(L"BackgroundImageSettingsVisible");
|
||||
}
|
||||
else if (viewModelProperty == L"StartingDirectory")
|
||||
{
|
||||
// notify listener that all starting directory related values might have changed
|
||||
// NOTE: this is similar to what is done with BackgroundImagePath above
|
||||
_NotifyChanges(L"UseParentProcessDirectory", L"UseCustomStartingDirectory");
|
||||
}
|
||||
else if (viewModelProperty == L"UseAcrylic")
|
||||
{
|
||||
// GH#11372: If we're on Windows 10, and someone turns off
|
||||
// acrylic, we're going to disable opacity for them. Opacity
|
||||
// doesn't work without acrylic on Windows 10.
|
||||
//
|
||||
// BODGY: CascadiaSettings's function IsDefaultTerminalAvailable
|
||||
// is basically a "are we on Windows 11" check, because defterm
|
||||
// only works on Win11. So we'll use that.
|
||||
//
|
||||
// Remove when we can remove the rest of GH#11285
|
||||
if (!UseAcrylic() && !CascadiaSettings::IsDefaultTerminalAvailable())
|
||||
{
|
||||
Opacity(1.0);
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
// Do the same for the starting directory
|
||||
if (!StartingDirectory().empty())
|
||||
{
|
||||
_lastStartingDirectoryPath = StartingDirectory();
|
||||
}
|
||||
|
||||
// generate the font list, if we don't have one
|
||||
if (!_FontList || !_MonospaceFontList)
|
||||
{
|
||||
UpdateFontList();
|
||||
}
|
||||
|
||||
if (profile.HasUnfocusedAppearance())
|
||||
{
|
||||
_unfocusedAppearanceViewModel = winrt::make<implementation::AppearanceViewModel>(profile.UnfocusedAppearance().try_as<AppearanceConfig>());
|
||||
}
|
||||
|
||||
_defaultAppearanceViewModel.IsDefault(true);
|
||||
}
|
||||
|
||||
Model::TerminalSettings ProfileViewModel::TermSettings() const
|
||||
{
|
||||
return Model::TerminalSettings::CreateWithProfile(_appSettings, _profile, nullptr).DefaultSettings();
|
||||
}
|
||||
|
||||
// Method Description:
|
||||
// - Updates the lists of fonts and sorts them alphabetically
|
||||
void ProfileViewModel::UpdateFontList() noexcept
|
||||
try
|
||||
{
|
||||
// initialize font list
|
||||
std::vector<Editor::Font> fontList;
|
||||
std::vector<Editor::Font> monospaceFontList;
|
||||
|
||||
// get a DWriteFactory
|
||||
com_ptr<IDWriteFactory> factory;
|
||||
THROW_IF_FAILED(DWriteCreateFactory(
|
||||
DWRITE_FACTORY_TYPE_SHARED,
|
||||
__uuidof(IDWriteFactory),
|
||||
reinterpret_cast<::IUnknown**>(factory.put())));
|
||||
|
||||
// get the font collection; subscribe to updates
|
||||
const auto fontCollection = NearbyCollection(factory.get());
|
||||
|
||||
for (UINT32 i = 0; i < fontCollection->GetFontFamilyCount(); ++i)
|
||||
{
|
||||
try
|
||||
{
|
||||
// get the font family
|
||||
com_ptr<IDWriteFontFamily> fontFamily;
|
||||
THROW_IF_FAILED(fontCollection->GetFontFamily(i, fontFamily.put()));
|
||||
|
||||
// get the font's localized names
|
||||
com_ptr<IDWriteLocalizedStrings> localizedFamilyNames;
|
||||
THROW_IF_FAILED(fontFamily->GetFamilyNames(localizedFamilyNames.put()));
|
||||
|
||||
// construct a font entry for tracking
|
||||
if (const auto fontEntry{ _GetFont(localizedFamilyNames) })
|
||||
{
|
||||
// check if the font is monospaced
|
||||
try
|
||||
{
|
||||
com_ptr<IDWriteFont> font;
|
||||
THROW_IF_FAILED(fontFamily->GetFirstMatchingFont(DWRITE_FONT_WEIGHT::DWRITE_FONT_WEIGHT_NORMAL,
|
||||
DWRITE_FONT_STRETCH::DWRITE_FONT_STRETCH_NORMAL,
|
||||
DWRITE_FONT_STYLE::DWRITE_FONT_STYLE_NORMAL,
|
||||
font.put()));
|
||||
|
||||
// add the font name to our list of monospace fonts
|
||||
const auto castedFont{ font.try_as<IDWriteFont1>() };
|
||||
if (castedFont && castedFont->IsMonospacedFont())
|
||||
{
|
||||
monospaceFontList.emplace_back(fontEntry);
|
||||
}
|
||||
}
|
||||
CATCH_LOG();
|
||||
|
||||
// add the font name to our list of all fonts
|
||||
fontList.emplace_back(std::move(fontEntry));
|
||||
}
|
||||
}
|
||||
CATCH_LOG();
|
||||
}
|
||||
|
||||
// sort and save the lists
|
||||
std::sort(begin(fontList), end(fontList), FontComparator());
|
||||
_FontList = single_threaded_observable_vector<Editor::Font>(std::move(fontList));
|
||||
|
||||
std::sort(begin(monospaceFontList), end(monospaceFontList), FontComparator());
|
||||
_MonospaceFontList = single_threaded_observable_vector<Editor::Font>(std::move(monospaceFontList));
|
||||
}
|
||||
CATCH_LOG();
|
||||
|
||||
Editor::Font ProfileViewModel::_GetFont(com_ptr<IDWriteLocalizedStrings> localizedFamilyNames)
|
||||
{
|
||||
// used for the font's name as an identifier (i.e. text block's font family property)
|
||||
std::wstring nameID;
|
||||
UINT32 nameIDIndex;
|
||||
|
||||
// used for the font's localized name
|
||||
std::wstring localizedName;
|
||||
UINT32 localizedNameIndex;
|
||||
|
||||
// use our current locale to find the localized name
|
||||
BOOL exists{ FALSE };
|
||||
HRESULT hr;
|
||||
wchar_t localeName[LOCALE_NAME_MAX_LENGTH];
|
||||
if (GetUserDefaultLocaleName(localeName, LOCALE_NAME_MAX_LENGTH))
|
||||
{
|
||||
hr = localizedFamilyNames->FindLocaleName(localeName, &localizedNameIndex, &exists);
|
||||
}
|
||||
if (SUCCEEDED(hr) && !exists)
|
||||
{
|
||||
// if we can't find the font for our locale, fallback to the en-us one
|
||||
// Source: https://docs.microsoft.com/en-us/windows/win32/api/dwrite/nf-dwrite-idwritelocalizedstrings-findlocalename
|
||||
hr = localizedFamilyNames->FindLocaleName(L"en-us", &localizedNameIndex, &exists);
|
||||
}
|
||||
if (!exists)
|
||||
{
|
||||
// failed to find the correct locale, using the first one
|
||||
localizedNameIndex = 0;
|
||||
}
|
||||
|
||||
// get the localized name
|
||||
UINT32 nameLength;
|
||||
THROW_IF_FAILED(localizedFamilyNames->GetStringLength(localizedNameIndex, &nameLength));
|
||||
|
||||
localizedName.resize(nameLength);
|
||||
THROW_IF_FAILED(localizedFamilyNames->GetString(localizedNameIndex, localizedName.data(), nameLength + 1));
|
||||
|
||||
// now get the nameID
|
||||
hr = localizedFamilyNames->FindLocaleName(L"en-us", &nameIDIndex, &exists);
|
||||
if (FAILED(hr) || !exists)
|
||||
{
|
||||
// failed to find it, using the first one
|
||||
nameIDIndex = 0;
|
||||
}
|
||||
|
||||
// get the nameID
|
||||
THROW_IF_FAILED(localizedFamilyNames->GetStringLength(nameIDIndex, &nameLength));
|
||||
nameID.resize(nameLength);
|
||||
THROW_IF_FAILED(localizedFamilyNames->GetString(nameIDIndex, nameID.data(), nameLength + 1));
|
||||
|
||||
if (!nameID.empty() && !localizedName.empty())
|
||||
{
|
||||
return make<Font>(nameID, localizedName);
|
||||
}
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
Windows::Foundation::Collections::IMapView<hstring, Model::ColorScheme> ProfileViewModel::Schemes() const noexcept
|
||||
{
|
||||
return _Schemes;
|
||||
}
|
||||
|
||||
void ProfileViewModel::Schemes(const Windows::Foundation::Collections::IMapView<hstring, Model::ColorScheme>& val) noexcept
|
||||
{
|
||||
_Schemes = val;
|
||||
}
|
||||
|
||||
winrt::guid ProfileViewModel::OriginalProfileGuid() const noexcept
|
||||
{
|
||||
return _originalProfileGuid;
|
||||
}
|
||||
|
||||
bool ProfileViewModel::CanDeleteProfile() const
|
||||
{
|
||||
return !IsBaseLayer();
|
||||
}
|
||||
|
||||
Editor::AppearanceViewModel ProfileViewModel::DefaultAppearance()
|
||||
{
|
||||
return _defaultAppearanceViewModel;
|
||||
}
|
||||
|
||||
bool ProfileViewModel::HasUnfocusedAppearance()
|
||||
{
|
||||
return _profile.HasUnfocusedAppearance();
|
||||
}
|
||||
|
||||
bool ProfileViewModel::EditableUnfocusedAppearance() const noexcept
|
||||
{
|
||||
return Feature_EditableUnfocusedAppearance::IsEnabled();
|
||||
}
|
||||
|
||||
bool ProfileViewModel::ShowUnfocusedAppearance()
|
||||
{
|
||||
return EditableUnfocusedAppearance() && HasUnfocusedAppearance();
|
||||
}
|
||||
|
||||
void ProfileViewModel::CreateUnfocusedAppearance()
|
||||
{
|
||||
_profile.CreateUnfocusedAppearance();
|
||||
|
||||
_unfocusedAppearanceViewModel = winrt::make<implementation::AppearanceViewModel>(_profile.UnfocusedAppearance().try_as<AppearanceConfig>());
|
||||
_unfocusedAppearanceViewModel.Schemes(_Schemes);
|
||||
_unfocusedAppearanceViewModel.WindowRoot(_WindowRoot);
|
||||
|
||||
_NotifyChanges(L"UnfocusedAppearance", L"HasUnfocusedAppearance", L"ShowUnfocusedAppearance");
|
||||
}
|
||||
|
||||
void ProfileViewModel::DeleteUnfocusedAppearance()
|
||||
{
|
||||
_profile.DeleteUnfocusedAppearance();
|
||||
|
||||
_unfocusedAppearanceViewModel = nullptr;
|
||||
|
||||
_NotifyChanges(L"UnfocusedAppearance", L"HasUnfocusedAppearance", L"ShowUnfocusedAppearance");
|
||||
}
|
||||
|
||||
Editor::AppearanceViewModel ProfileViewModel::UnfocusedAppearance()
|
||||
{
|
||||
return _unfocusedAppearanceViewModel;
|
||||
}
|
||||
|
||||
bool ProfileViewModel::AtlasEngineAvailable() const noexcept
|
||||
{
|
||||
return Feature_AtlasEngine::IsEnabled();
|
||||
}
|
||||
|
||||
bool ProfileViewModel::UseParentProcessDirectory()
|
||||
{
|
||||
return StartingDirectory().empty();
|
||||
}
|
||||
|
||||
// This function simply returns the opposite of UseParentProcessDirectory.
|
||||
// We bind the 'IsEnabled' parameters of the textbox and browse button
|
||||
// to this because it needs to be the reverse of UseParentProcessDirectory
|
||||
// but we don't want to create a whole new converter for inverting a boolean
|
||||
bool ProfileViewModel::UseCustomStartingDirectory()
|
||||
{
|
||||
return !UseParentProcessDirectory();
|
||||
}
|
||||
|
||||
void ProfileViewModel::UseParentProcessDirectory(const bool useParent)
|
||||
{
|
||||
if (useParent)
|
||||
{
|
||||
// Stash the current value of StartingDirectory. If the user
|
||||
// checks and un-checks the "Use parent process directory" button, we want
|
||||
// the path that we display in the text box to remain unchanged.
|
||||
//
|
||||
// Only stash this value if it's not empty
|
||||
if (!StartingDirectory().empty())
|
||||
{
|
||||
_lastStartingDirectoryPath = StartingDirectory();
|
||||
}
|
||||
StartingDirectory(L"");
|
||||
}
|
||||
else
|
||||
{
|
||||
// Restore the path we had previously cached as long as it wasn't empty
|
||||
// If it was empty, set the starting directory to %USERPROFILE%
|
||||
// (we need to set it to something non-empty otherwise we will automatically
|
||||
// disable the text box)
|
||||
if (_lastStartingDirectoryPath.empty())
|
||||
{
|
||||
StartingDirectory(L"%USERPROFILE%");
|
||||
}
|
||||
else
|
||||
{
|
||||
StartingDirectory(_lastStartingDirectoryPath);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
bool ProfileViewModel::IsBellStyleFlagSet(const uint32_t flag)
|
||||
{
|
||||
return (WI_EnumValue(BellStyle()) & flag) == flag;
|
||||
}
|
||||
|
||||
void ProfileViewModel::SetBellStyleAudible(winrt::Windows::Foundation::IReference<bool> on)
|
||||
{
|
||||
auto currentStyle = BellStyle();
|
||||
WI_UpdateFlag(currentStyle, Model::BellStyle::Audible, winrt::unbox_value<bool>(on));
|
||||
BellStyle(currentStyle);
|
||||
}
|
||||
|
||||
void ProfileViewModel::SetBellStyleWindow(winrt::Windows::Foundation::IReference<bool> on)
|
||||
{
|
||||
auto currentStyle = BellStyle();
|
||||
WI_UpdateFlag(currentStyle, Model::BellStyle::Window, winrt::unbox_value<bool>(on));
|
||||
BellStyle(currentStyle);
|
||||
}
|
||||
|
||||
void ProfileViewModel::SetBellStyleTaskbar(winrt::Windows::Foundation::IReference<bool> on)
|
||||
{
|
||||
auto currentStyle = BellStyle();
|
||||
WI_UpdateFlag(currentStyle, Model::BellStyle::Taskbar, winrt::unbox_value<bool>(on));
|
||||
BellStyle(currentStyle);
|
||||
}
|
||||
|
||||
void ProfileViewModel::DeleteProfile()
|
||||
{
|
||||
auto deleteProfileArgs{ winrt::make_self<DeleteProfileEventArgs>(Guid()) };
|
||||
_DeleteProfileHandlers(*this, *deleteProfileArgs);
|
||||
}
|
||||
}
|
||||
151
src/cascadia/TerminalSettingsEditor/ProfileViewModel.h
Normal file
151
src/cascadia/TerminalSettingsEditor/ProfileViewModel.h
Normal file
@@ -0,0 +1,151 @@
|
||||
// Copyright (c) Microsoft Corporation.
|
||||
// Licensed under the MIT license.
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "DeleteProfileEventArgs.g.h"
|
||||
#include "ProfileViewModel.g.h"
|
||||
#include "Utils.h"
|
||||
#include "ViewModelHelpers.h"
|
||||
#include "Appearances.h"
|
||||
|
||||
namespace winrt::Microsoft::Terminal::Settings::Editor::implementation
|
||||
{
|
||||
struct ProfileViewModel : ProfileViewModelT<ProfileViewModel>, ViewModelHelper<ProfileViewModel>
|
||||
{
|
||||
public:
|
||||
// font face
|
||||
static void UpdateFontList() noexcept;
|
||||
static Windows::Foundation::Collections::IObservableVector<Editor::Font> CompleteFontList() noexcept { return _FontList; };
|
||||
static Windows::Foundation::Collections::IObservableVector<Editor::Font> MonospaceFontList() noexcept { return _MonospaceFontList; };
|
||||
|
||||
static ProfilesPivots LastActivePivot() noexcept { return _LastActivePivot; };
|
||||
static void LastActivePivot(Editor::ProfilesPivots val) noexcept { _LastActivePivot = val; };
|
||||
|
||||
ProfileViewModel(const Model::Profile& profile, const Model::CascadiaSettings& settings);
|
||||
Model::TerminalSettings TermSettings() const;
|
||||
void DeleteProfile();
|
||||
|
||||
Windows::Foundation::Collections::IMapView<hstring, Model::ColorScheme> Schemes() const noexcept;
|
||||
void Schemes(const Windows::Foundation::Collections::IMapView<hstring, Model::ColorScheme>& val) noexcept;
|
||||
|
||||
// bell style bits
|
||||
bool IsBellStyleFlagSet(const uint32_t flag);
|
||||
void SetBellStyleAudible(winrt::Windows::Foundation::IReference<bool> on);
|
||||
void SetBellStyleWindow(winrt::Windows::Foundation::IReference<bool> on);
|
||||
void SetBellStyleTaskbar(winrt::Windows::Foundation::IReference<bool> on);
|
||||
|
||||
void SetAcrylicOpacityPercentageValue(double value)
|
||||
{
|
||||
Opacity(winrt::Microsoft::Terminal::Settings::Editor::Converters::PercentageValueToPercentage(value));
|
||||
|
||||
// GH#11372: If we're on Windows 10, and someone wants opacity, then
|
||||
// we'll turn acrylic on for them. Opacity doesn't work without
|
||||
// acrylic on Windows 10.
|
||||
//
|
||||
// BODGY: CascadiaSettings's function IsDefaultTerminalAvailable
|
||||
// is basically a "are we on Windows 11" check, because defterm
|
||||
// only works on Win11. So we'll use that.
|
||||
//
|
||||
// Remove when we can remove the rest of GH#11285
|
||||
if (value < 100.0 &&
|
||||
!winrt::Microsoft::Terminal::Settings::Model::CascadiaSettings::IsDefaultTerminalAvailable())
|
||||
{
|
||||
UseAcrylic(true);
|
||||
}
|
||||
};
|
||||
|
||||
void SetPadding(double value)
|
||||
{
|
||||
Padding(to_hstring(value));
|
||||
}
|
||||
|
||||
// starting directory
|
||||
bool UseParentProcessDirectory();
|
||||
void UseParentProcessDirectory(const bool useParent);
|
||||
bool UseCustomStartingDirectory();
|
||||
|
||||
// general profile knowledge
|
||||
winrt::guid OriginalProfileGuid() const noexcept;
|
||||
bool CanDeleteProfile() const;
|
||||
Editor::AppearanceViewModel DefaultAppearance();
|
||||
Editor::AppearanceViewModel UnfocusedAppearance();
|
||||
bool HasUnfocusedAppearance();
|
||||
bool EditableUnfocusedAppearance() const noexcept;
|
||||
bool ShowUnfocusedAppearance();
|
||||
void CreateUnfocusedAppearance();
|
||||
void DeleteUnfocusedAppearance();
|
||||
bool AtlasEngineAvailable() const noexcept;
|
||||
|
||||
WINRT_PROPERTY(bool, IsBaseLayer, false);
|
||||
WINRT_PROPERTY(IHostedInWindow, WindowRoot, nullptr);
|
||||
GETSET_BINDABLE_ENUM_SETTING(AntiAliasingMode, Microsoft::Terminal::Control::TextAntialiasingMode, _profile, AntialiasingMode);
|
||||
GETSET_BINDABLE_ENUM_SETTING(CloseOnExitMode, Microsoft::Terminal::Settings::Model::CloseOnExitMode, _profile, CloseOnExit);
|
||||
GETSET_BINDABLE_ENUM_SETTING(ScrollState, Microsoft::Terminal::Control::ScrollbarState, _profile, ScrollState);
|
||||
|
||||
PERMANENT_OBSERVABLE_PROJECTED_SETTING(_profile, Guid);
|
||||
PERMANENT_OBSERVABLE_PROJECTED_SETTING(_profile, ConnectionType);
|
||||
OBSERVABLE_PROJECTED_SETTING(_profile, Name);
|
||||
OBSERVABLE_PROJECTED_SETTING(_profile, Source);
|
||||
OBSERVABLE_PROJECTED_SETTING(_profile, Hidden);
|
||||
OBSERVABLE_PROJECTED_SETTING(_profile, Icon);
|
||||
OBSERVABLE_PROJECTED_SETTING(_profile, CloseOnExit);
|
||||
OBSERVABLE_PROJECTED_SETTING(_profile, TabTitle);
|
||||
OBSERVABLE_PROJECTED_SETTING(_profile, TabColor);
|
||||
OBSERVABLE_PROJECTED_SETTING(_profile, SuppressApplicationTitle);
|
||||
OBSERVABLE_PROJECTED_SETTING(_profile, UseAcrylic);
|
||||
OBSERVABLE_PROJECTED_SETTING(_profile, ScrollState);
|
||||
OBSERVABLE_PROJECTED_SETTING(_profile, Padding);
|
||||
OBSERVABLE_PROJECTED_SETTING(_profile, Commandline);
|
||||
OBSERVABLE_PROJECTED_SETTING(_profile, StartingDirectory);
|
||||
OBSERVABLE_PROJECTED_SETTING(_profile, AntialiasingMode);
|
||||
OBSERVABLE_PROJECTED_SETTING(_profile.DefaultAppearance(), Foreground);
|
||||
OBSERVABLE_PROJECTED_SETTING(_profile.DefaultAppearance(), Background);
|
||||
OBSERVABLE_PROJECTED_SETTING(_profile.DefaultAppearance(), SelectionBackground);
|
||||
OBSERVABLE_PROJECTED_SETTING(_profile.DefaultAppearance(), CursorColor);
|
||||
OBSERVABLE_PROJECTED_SETTING(_profile.DefaultAppearance(), Opacity);
|
||||
OBSERVABLE_PROJECTED_SETTING(_profile, HistorySize);
|
||||
OBSERVABLE_PROJECTED_SETTING(_profile, SnapOnInput);
|
||||
OBSERVABLE_PROJECTED_SETTING(_profile, AltGrAliasing);
|
||||
OBSERVABLE_PROJECTED_SETTING(_profile, BellStyle);
|
||||
OBSERVABLE_PROJECTED_SETTING(_profile, UseAtlasEngine);
|
||||
|
||||
TYPED_EVENT(DeleteProfile, Editor::ProfileViewModel, Editor::DeleteProfileEventArgs);
|
||||
|
||||
private:
|
||||
Model::Profile _profile;
|
||||
winrt::guid _originalProfileGuid;
|
||||
winrt::hstring _lastBgImagePath;
|
||||
winrt::hstring _lastStartingDirectoryPath;
|
||||
Editor::AppearanceViewModel _defaultAppearanceViewModel;
|
||||
Windows::Foundation::Collections::IMapView<hstring, Model::ColorScheme> _Schemes;
|
||||
|
||||
static Windows::Foundation::Collections::IObservableVector<Editor::Font> _MonospaceFontList;
|
||||
static Windows::Foundation::Collections::IObservableVector<Editor::Font> _FontList;
|
||||
static ProfilesPivots _LastActivePivot;
|
||||
|
||||
static Editor::Font _GetFont(com_ptr<IDWriteLocalizedStrings> localizedFamilyNames);
|
||||
|
||||
Model::CascadiaSettings _appSettings;
|
||||
Editor::AppearanceViewModel _unfocusedAppearanceViewModel;
|
||||
};
|
||||
|
||||
struct DeleteProfileEventArgs :
|
||||
public DeleteProfileEventArgsT<DeleteProfileEventArgs>
|
||||
{
|
||||
public:
|
||||
DeleteProfileEventArgs(guid profileGuid) :
|
||||
_ProfileGuid(profileGuid) {}
|
||||
|
||||
guid ProfileGuid() const noexcept { return _ProfileGuid; }
|
||||
|
||||
private:
|
||||
guid _ProfileGuid{};
|
||||
};
|
||||
};
|
||||
|
||||
namespace winrt::Microsoft::Terminal::Settings::Editor::factory_implementation
|
||||
{
|
||||
// Since we have static functions, we need a factory.
|
||||
BASIC_FACTORY(ProfileViewModel);
|
||||
}
|
||||
97
src/cascadia/TerminalSettingsEditor/ProfileViewModel.idl
Normal file
97
src/cascadia/TerminalSettingsEditor/ProfileViewModel.idl
Normal file
@@ -0,0 +1,97 @@
|
||||
// Copyright (c) Microsoft Corporation.
|
||||
// Licensed under the MIT license.
|
||||
|
||||
import "EnumEntry.idl";
|
||||
import "MainPage.idl";
|
||||
import "Appearances.idl";
|
||||
|
||||
#include "ViewModelHelpers.idl.h"
|
||||
|
||||
#define OBSERVABLE_PROJECTED_PROFILE_SETTING(Type, Name) \
|
||||
OBSERVABLE_PROJECTED_SETTING(Type, Name); \
|
||||
Object Name##OverrideSource { get; }
|
||||
|
||||
namespace Microsoft.Terminal.Settings.Editor
|
||||
{
|
||||
runtimeclass DeleteProfileEventArgs
|
||||
{
|
||||
Guid ProfileGuid { get; };
|
||||
}
|
||||
|
||||
enum ProfilesPivots
|
||||
{
|
||||
General = 0,
|
||||
Appearance = 1,
|
||||
Advanced = 2
|
||||
};
|
||||
|
||||
runtimeclass ProfileViewModel : Windows.UI.Xaml.Data.INotifyPropertyChanged
|
||||
{
|
||||
static Windows.Foundation.Collections.IObservableVector<Font> CompleteFontList { get; };
|
||||
static Windows.Foundation.Collections.IObservableVector<Font> MonospaceFontList { get; };
|
||||
static ProfilesPivots LastActivePivot;
|
||||
|
||||
Microsoft.Terminal.Settings.Model.TerminalSettings TermSettings { get; };
|
||||
|
||||
event Windows.Foundation.TypedEventHandler<ProfileViewModel, DeleteProfileEventArgs> DeleteProfile;
|
||||
|
||||
void SetAcrylicOpacityPercentageValue(Double value);
|
||||
void SetPadding(Double value);
|
||||
|
||||
Boolean IsBellStyleFlagSet(UInt32 flag);
|
||||
void SetBellStyleAudible(Windows.Foundation.IReference<Boolean> on);
|
||||
void SetBellStyleWindow(Windows.Foundation.IReference<Boolean> on);
|
||||
void SetBellStyleTaskbar(Windows.Foundation.IReference<Boolean> on);
|
||||
|
||||
IInspectable CurrentAntiAliasingMode;
|
||||
Windows.Foundation.Collections.IObservableVector<Microsoft.Terminal.Settings.Editor.EnumEntry> AntiAliasingModeList { get; };
|
||||
|
||||
IInspectable CurrentCloseOnExitMode;
|
||||
Windows.Foundation.Collections.IObservableVector<Microsoft.Terminal.Settings.Editor.EnumEntry> CloseOnExitModeList { get; };
|
||||
|
||||
IInspectable CurrentScrollState;
|
||||
Windows.Foundation.Collections.IObservableVector<Microsoft.Terminal.Settings.Editor.EnumEntry> ScrollStateList { get; };
|
||||
|
||||
Boolean CanDeleteProfile { get; };
|
||||
Boolean IsBaseLayer;
|
||||
Boolean UseParentProcessDirectory;
|
||||
Boolean UseCustomStartingDirectory { get; };
|
||||
AppearanceViewModel DefaultAppearance { get; };
|
||||
Guid OriginalProfileGuid { get; };
|
||||
Boolean HasUnfocusedAppearance { get; };
|
||||
Boolean EditableUnfocusedAppearance { get; };
|
||||
Boolean ShowUnfocusedAppearance { get; };
|
||||
AppearanceViewModel UnfocusedAppearance { get; };
|
||||
Boolean AtlasEngineAvailable { get; };
|
||||
|
||||
void CreateUnfocusedAppearance();
|
||||
void DeleteUnfocusedAppearance();
|
||||
|
||||
OBSERVABLE_PROJECTED_PROFILE_SETTING(String, Name);
|
||||
PERMANENT_OBSERVABLE_PROJECTED_SETTING(Guid, Guid);
|
||||
OBSERVABLE_PROJECTED_PROFILE_SETTING(String, Source);
|
||||
PERMANENT_OBSERVABLE_PROJECTED_SETTING(Guid, ConnectionType);
|
||||
OBSERVABLE_PROJECTED_PROFILE_SETTING(Boolean, Hidden);
|
||||
OBSERVABLE_PROJECTED_PROFILE_SETTING(String, Icon);
|
||||
OBSERVABLE_PROJECTED_PROFILE_SETTING(Microsoft.Terminal.Settings.Model.CloseOnExitMode, CloseOnExit);
|
||||
OBSERVABLE_PROJECTED_PROFILE_SETTING(String, TabTitle);
|
||||
OBSERVABLE_PROJECTED_PROFILE_SETTING(Windows.Foundation.IReference<Microsoft.Terminal.Core.Color>, TabColor);
|
||||
OBSERVABLE_PROJECTED_PROFILE_SETTING(Boolean, SuppressApplicationTitle);
|
||||
OBSERVABLE_PROJECTED_PROFILE_SETTING(Boolean, UseAcrylic);
|
||||
OBSERVABLE_PROJECTED_PROFILE_SETTING(Double, Opacity);
|
||||
OBSERVABLE_PROJECTED_PROFILE_SETTING(Microsoft.Terminal.Control.ScrollbarState, ScrollState);
|
||||
OBSERVABLE_PROJECTED_PROFILE_SETTING(String, Padding);
|
||||
OBSERVABLE_PROJECTED_PROFILE_SETTING(String, Commandline);
|
||||
OBSERVABLE_PROJECTED_PROFILE_SETTING(String, StartingDirectory);
|
||||
OBSERVABLE_PROJECTED_PROFILE_SETTING(Microsoft.Terminal.Control.TextAntialiasingMode, AntialiasingMode);
|
||||
OBSERVABLE_PROJECTED_PROFILE_SETTING(Windows.Foundation.IReference<Microsoft.Terminal.Core.Color>, Foreground);
|
||||
OBSERVABLE_PROJECTED_PROFILE_SETTING(Windows.Foundation.IReference<Microsoft.Terminal.Core.Color>, Background);
|
||||
OBSERVABLE_PROJECTED_PROFILE_SETTING(Windows.Foundation.IReference<Microsoft.Terminal.Core.Color>, SelectionBackground);
|
||||
OBSERVABLE_PROJECTED_PROFILE_SETTING(Windows.Foundation.IReference<Microsoft.Terminal.Core.Color>, CursorColor);
|
||||
OBSERVABLE_PROJECTED_PROFILE_SETTING(Int32, HistorySize);
|
||||
OBSERVABLE_PROJECTED_PROFILE_SETTING(Boolean, SnapOnInput);
|
||||
OBSERVABLE_PROJECTED_PROFILE_SETTING(Boolean, AltGrAliasing);
|
||||
OBSERVABLE_PROJECTED_PROFILE_SETTING(Microsoft.Terminal.Settings.Model.BellStyle, BellStyle);
|
||||
OBSERVABLE_PROJECTED_PROFILE_SETTING(Boolean, UseAtlasEngine);
|
||||
}
|
||||
}
|
||||
@@ -6,59 +6,10 @@
|
||||
|
||||
#include "PreviewConnection.h"
|
||||
#include "Profiles.g.cpp"
|
||||
#include "EnumEntry.h"
|
||||
|
||||
#include <LibraryResources.h>
|
||||
#include "..\WinRTUtils\inc\Utils.h"
|
||||
|
||||
// This function is a copy of DxFontInfo::_NearbyCollection() with
|
||||
// * the call to DxFontInfo::s_GetNearbyFonts() inlined
|
||||
// * checkForUpdates for GetSystemFontCollection() set to true
|
||||
static wil::com_ptr<IDWriteFontCollection1> NearbyCollection(IDWriteFactory* dwriteFactory)
|
||||
{
|
||||
// The convenience interfaces for loading fonts from files
|
||||
// are only available on Windows 10+.
|
||||
wil::com_ptr<IDWriteFactory6> factory6;
|
||||
// wil's query() facilities don't work inside WinRT land at the moment.
|
||||
// They produce a compilation error due to IUnknown and winrt::Windows::Foundation::IUnknown being ambiguous.
|
||||
if (!SUCCEEDED(dwriteFactory->QueryInterface(__uuidof(IDWriteFactory6), factory6.put_void())))
|
||||
{
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
wil::com_ptr<IDWriteFontCollection1> systemFontCollection;
|
||||
THROW_IF_FAILED(factory6->GetSystemFontCollection(false, systemFontCollection.addressof(), true));
|
||||
|
||||
wil::com_ptr<IDWriteFontSet> systemFontSet;
|
||||
THROW_IF_FAILED(systemFontCollection->GetFontSet(systemFontSet.addressof()));
|
||||
|
||||
wil::com_ptr<IDWriteFontSetBuilder2> fontSetBuilder2;
|
||||
THROW_IF_FAILED(factory6->CreateFontSetBuilder(fontSetBuilder2.addressof()));
|
||||
|
||||
THROW_IF_FAILED(fontSetBuilder2->AddFontSet(systemFontSet.get()));
|
||||
|
||||
{
|
||||
const std::filesystem::path module{ wil::GetModuleFileNameW<std::wstring>(nullptr) };
|
||||
const auto folder{ module.parent_path() };
|
||||
|
||||
for (const auto& p : std::filesystem::directory_iterator(folder))
|
||||
{
|
||||
if (til::ends_with(p.path().native(), L".ttf"))
|
||||
{
|
||||
fontSetBuilder2->AddFontFile(p.path().c_str());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
wil::com_ptr<IDWriteFontSet> fontSet;
|
||||
THROW_IF_FAILED(fontSetBuilder2->CreateFontSet(fontSet.addressof()));
|
||||
|
||||
wil::com_ptr<IDWriteFontCollection1> fontCollection;
|
||||
THROW_IF_FAILED(factory6->CreateFontCollectionFromFontSet(fontSet.get(), &fontCollection));
|
||||
|
||||
return fontCollection;
|
||||
}
|
||||
|
||||
using namespace winrt::Windows::UI::Text;
|
||||
using namespace winrt::Windows::UI::Xaml;
|
||||
using namespace winrt::Windows::UI::Xaml::Controls;
|
||||
@@ -70,342 +21,11 @@ using namespace winrt::Microsoft::Terminal::Settings::Model;
|
||||
|
||||
namespace winrt::Microsoft::Terminal::Settings::Editor::implementation
|
||||
{
|
||||
Windows::Foundation::Collections::IObservableVector<Editor::Font> ProfileViewModel::_MonospaceFontList{ nullptr };
|
||||
Windows::Foundation::Collections::IObservableVector<Editor::Font> ProfileViewModel::_FontList{ nullptr };
|
||||
|
||||
ProfileViewModel::ProfileViewModel(const Model::Profile& profile, const Model::CascadiaSettings& appSettings) :
|
||||
_profile{ profile },
|
||||
_defaultAppearanceViewModel{ winrt::make<implementation::AppearanceViewModel>(profile.DefaultAppearance().try_as<AppearanceConfig>()) },
|
||||
_originalProfileGuid{ profile.Guid() },
|
||||
_appSettings{ appSettings },
|
||||
_unfocusedAppearanceViewModel{ nullptr }
|
||||
{
|
||||
// Add a property changed handler to our own property changed event.
|
||||
// This propagates changes from the settings model to anybody listening to our
|
||||
// unique view model members.
|
||||
PropertyChanged([this](auto&&, const PropertyChangedEventArgs& args) {
|
||||
const auto viewModelProperty{ args.PropertyName() };
|
||||
if (viewModelProperty == L"IsBaseLayer")
|
||||
{
|
||||
// we _always_ want to show the background image settings in base layer
|
||||
_NotifyChanges(L"BackgroundImageSettingsVisible");
|
||||
}
|
||||
else if (viewModelProperty == L"StartingDirectory")
|
||||
{
|
||||
// notify listener that all starting directory related values might have changed
|
||||
// NOTE: this is similar to what is done with BackgroundImagePath above
|
||||
_NotifyChanges(L"UseParentProcessDirectory", L"UseCustomStartingDirectory");
|
||||
}
|
||||
else if (viewModelProperty == L"UseAcrylic")
|
||||
{
|
||||
// GH#11372: If we're on Windows 10, and someone turns off
|
||||
// acrylic, we're going to disable opacity for them. Opacity
|
||||
// doesn't work without acrylic on Windows 10.
|
||||
//
|
||||
// BODGY: CascadiaSettings's function IsDefaultTerminalAvailable
|
||||
// is basically a "are we on Windows 11" check, because defterm
|
||||
// only works on Win11. So we'll use that.
|
||||
//
|
||||
// Remove when we can remove the rest of GH#11285
|
||||
if (!UseAcrylic() && !CascadiaSettings::IsDefaultTerminalAvailable())
|
||||
{
|
||||
Opacity(1.0);
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
// Do the same for the starting directory
|
||||
if (!StartingDirectory().empty())
|
||||
{
|
||||
_lastStartingDirectoryPath = StartingDirectory();
|
||||
}
|
||||
|
||||
// generate the font list, if we don't have one
|
||||
if (!_FontList || !_MonospaceFontList)
|
||||
{
|
||||
UpdateFontList();
|
||||
}
|
||||
|
||||
if (profile.HasUnfocusedAppearance())
|
||||
{
|
||||
_unfocusedAppearanceViewModel = winrt::make<implementation::AppearanceViewModel>(profile.UnfocusedAppearance().try_as<AppearanceConfig>());
|
||||
}
|
||||
|
||||
_defaultAppearanceViewModel.IsDefault(true);
|
||||
}
|
||||
|
||||
Model::TerminalSettings ProfileViewModel::TermSettings() const
|
||||
{
|
||||
return Model::TerminalSettings::CreateWithProfile(_appSettings, _profile, nullptr).DefaultSettings();
|
||||
}
|
||||
|
||||
// Method Description:
|
||||
// - Updates the lists of fonts and sorts them alphabetically
|
||||
void ProfileViewModel::UpdateFontList() noexcept
|
||||
try
|
||||
{
|
||||
// initialize font list
|
||||
std::vector<Editor::Font> fontList;
|
||||
std::vector<Editor::Font> monospaceFontList;
|
||||
|
||||
// get a DWriteFactory
|
||||
com_ptr<IDWriteFactory> factory;
|
||||
THROW_IF_FAILED(DWriteCreateFactory(
|
||||
DWRITE_FACTORY_TYPE_SHARED,
|
||||
__uuidof(IDWriteFactory),
|
||||
reinterpret_cast<::IUnknown**>(factory.put())));
|
||||
|
||||
// get the font collection; subscribe to updates
|
||||
const auto fontCollection = NearbyCollection(factory.get());
|
||||
|
||||
for (UINT32 i = 0; i < fontCollection->GetFontFamilyCount(); ++i)
|
||||
{
|
||||
try
|
||||
{
|
||||
// get the font family
|
||||
com_ptr<IDWriteFontFamily> fontFamily;
|
||||
THROW_IF_FAILED(fontCollection->GetFontFamily(i, fontFamily.put()));
|
||||
|
||||
// get the font's localized names
|
||||
com_ptr<IDWriteLocalizedStrings> localizedFamilyNames;
|
||||
THROW_IF_FAILED(fontFamily->GetFamilyNames(localizedFamilyNames.put()));
|
||||
|
||||
// construct a font entry for tracking
|
||||
if (const auto fontEntry{ _GetFont(localizedFamilyNames) })
|
||||
{
|
||||
// check if the font is monospaced
|
||||
try
|
||||
{
|
||||
com_ptr<IDWriteFont> font;
|
||||
THROW_IF_FAILED(fontFamily->GetFirstMatchingFont(DWRITE_FONT_WEIGHT::DWRITE_FONT_WEIGHT_NORMAL,
|
||||
DWRITE_FONT_STRETCH::DWRITE_FONT_STRETCH_NORMAL,
|
||||
DWRITE_FONT_STYLE::DWRITE_FONT_STYLE_NORMAL,
|
||||
font.put()));
|
||||
|
||||
// add the font name to our list of monospace fonts
|
||||
const auto castedFont{ font.try_as<IDWriteFont1>() };
|
||||
if (castedFont && castedFont->IsMonospacedFont())
|
||||
{
|
||||
monospaceFontList.emplace_back(fontEntry);
|
||||
}
|
||||
}
|
||||
CATCH_LOG();
|
||||
|
||||
// add the font name to our list of all fonts
|
||||
fontList.emplace_back(std::move(fontEntry));
|
||||
}
|
||||
}
|
||||
CATCH_LOG();
|
||||
}
|
||||
|
||||
// sort and save the lists
|
||||
std::sort(begin(fontList), end(fontList), FontComparator());
|
||||
_FontList = single_threaded_observable_vector<Editor::Font>(std::move(fontList));
|
||||
|
||||
std::sort(begin(monospaceFontList), end(monospaceFontList), FontComparator());
|
||||
_MonospaceFontList = single_threaded_observable_vector<Editor::Font>(std::move(monospaceFontList));
|
||||
}
|
||||
CATCH_LOG();
|
||||
|
||||
Editor::Font ProfileViewModel::_GetFont(com_ptr<IDWriteLocalizedStrings> localizedFamilyNames)
|
||||
{
|
||||
// used for the font's name as an identifier (i.e. text block's font family property)
|
||||
std::wstring nameID;
|
||||
UINT32 nameIDIndex;
|
||||
|
||||
// used for the font's localized name
|
||||
std::wstring localizedName;
|
||||
UINT32 localizedNameIndex;
|
||||
|
||||
// use our current locale to find the localized name
|
||||
BOOL exists{ FALSE };
|
||||
HRESULT hr;
|
||||
wchar_t localeName[LOCALE_NAME_MAX_LENGTH];
|
||||
if (GetUserDefaultLocaleName(localeName, LOCALE_NAME_MAX_LENGTH))
|
||||
{
|
||||
hr = localizedFamilyNames->FindLocaleName(localeName, &localizedNameIndex, &exists);
|
||||
}
|
||||
if (SUCCEEDED(hr) && !exists)
|
||||
{
|
||||
// if we can't find the font for our locale, fallback to the en-us one
|
||||
// Source: https://docs.microsoft.com/en-us/windows/win32/api/dwrite/nf-dwrite-idwritelocalizedstrings-findlocalename
|
||||
hr = localizedFamilyNames->FindLocaleName(L"en-us", &localizedNameIndex, &exists);
|
||||
}
|
||||
if (!exists)
|
||||
{
|
||||
// failed to find the correct locale, using the first one
|
||||
localizedNameIndex = 0;
|
||||
}
|
||||
|
||||
// get the localized name
|
||||
UINT32 nameLength;
|
||||
THROW_IF_FAILED(localizedFamilyNames->GetStringLength(localizedNameIndex, &nameLength));
|
||||
|
||||
localizedName.resize(nameLength);
|
||||
THROW_IF_FAILED(localizedFamilyNames->GetString(localizedNameIndex, localizedName.data(), nameLength + 1));
|
||||
|
||||
// now get the nameID
|
||||
hr = localizedFamilyNames->FindLocaleName(L"en-us", &nameIDIndex, &exists);
|
||||
if (FAILED(hr) || !exists)
|
||||
{
|
||||
// failed to find it, using the first one
|
||||
nameIDIndex = 0;
|
||||
}
|
||||
|
||||
// get the nameID
|
||||
THROW_IF_FAILED(localizedFamilyNames->GetStringLength(nameIDIndex, &nameLength));
|
||||
nameID.resize(nameLength);
|
||||
THROW_IF_FAILED(localizedFamilyNames->GetString(nameIDIndex, nameID.data(), nameLength + 1));
|
||||
|
||||
if (!nameID.empty() && !localizedName.empty())
|
||||
{
|
||||
return make<Font>(nameID, localizedName);
|
||||
}
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
IObservableVector<Editor::Font> ProfileViewModel::CompleteFontList() const noexcept
|
||||
{
|
||||
return _FontList;
|
||||
}
|
||||
|
||||
IObservableVector<Editor::Font> ProfileViewModel::MonospaceFontList() const noexcept
|
||||
{
|
||||
return _MonospaceFontList;
|
||||
}
|
||||
|
||||
winrt::guid ProfileViewModel::OriginalProfileGuid() const noexcept
|
||||
{
|
||||
return _originalProfileGuid;
|
||||
}
|
||||
|
||||
bool ProfileViewModel::CanDeleteProfile() const
|
||||
{
|
||||
return !IsBaseLayer();
|
||||
}
|
||||
|
||||
Editor::AppearanceViewModel ProfileViewModel::DefaultAppearance()
|
||||
{
|
||||
return _defaultAppearanceViewModel;
|
||||
}
|
||||
|
||||
bool ProfileViewModel::HasUnfocusedAppearance()
|
||||
{
|
||||
return _profile.HasUnfocusedAppearance();
|
||||
}
|
||||
|
||||
bool ProfileViewModel::EditableUnfocusedAppearance() const noexcept
|
||||
{
|
||||
return Feature_EditableUnfocusedAppearance::IsEnabled();
|
||||
}
|
||||
|
||||
bool ProfileViewModel::ShowUnfocusedAppearance()
|
||||
{
|
||||
return EditableUnfocusedAppearance() && HasUnfocusedAppearance();
|
||||
}
|
||||
|
||||
void ProfileViewModel::CreateUnfocusedAppearance(const Windows::Foundation::Collections::IMapView<hstring, Model::ColorScheme>& schemes,
|
||||
const IHostedInWindow& windowRoot)
|
||||
{
|
||||
_profile.CreateUnfocusedAppearance();
|
||||
|
||||
_unfocusedAppearanceViewModel = winrt::make<implementation::AppearanceViewModel>(_profile.UnfocusedAppearance().try_as<AppearanceConfig>());
|
||||
_unfocusedAppearanceViewModel.Schemes(schemes);
|
||||
_unfocusedAppearanceViewModel.WindowRoot(windowRoot);
|
||||
|
||||
_NotifyChanges(L"UnfocusedAppearance", L"HasUnfocusedAppearance", L"ShowUnfocusedAppearance");
|
||||
}
|
||||
|
||||
void ProfileViewModel::DeleteUnfocusedAppearance()
|
||||
{
|
||||
_profile.DeleteUnfocusedAppearance();
|
||||
|
||||
_unfocusedAppearanceViewModel = nullptr;
|
||||
|
||||
_NotifyChanges(L"UnfocusedAppearance", L"HasUnfocusedAppearance", L"ShowUnfocusedAppearance");
|
||||
}
|
||||
|
||||
Editor::AppearanceViewModel ProfileViewModel::UnfocusedAppearance()
|
||||
{
|
||||
return _unfocusedAppearanceViewModel;
|
||||
}
|
||||
|
||||
bool ProfileViewModel::AtlasEngineAvailable() const noexcept
|
||||
{
|
||||
return Feature_AtlasEngine::IsEnabled();
|
||||
}
|
||||
|
||||
bool ProfileViewModel::UseParentProcessDirectory()
|
||||
{
|
||||
return StartingDirectory().empty();
|
||||
}
|
||||
|
||||
// This function simply returns the opposite of UseParentProcessDirectory.
|
||||
// We bind the 'IsEnabled' parameters of the textbox and browse button
|
||||
// to this because it needs to be the reverse of UseParentProcessDirectory
|
||||
// but we don't want to create a whole new converter for inverting a boolean
|
||||
bool ProfileViewModel::UseCustomStartingDirectory()
|
||||
{
|
||||
return !UseParentProcessDirectory();
|
||||
}
|
||||
|
||||
void ProfileViewModel::UseParentProcessDirectory(const bool useParent)
|
||||
{
|
||||
if (useParent)
|
||||
{
|
||||
// Stash the current value of StartingDirectory. If the user
|
||||
// checks and un-checks the "Use parent process directory" button, we want
|
||||
// the path that we display in the text box to remain unchanged.
|
||||
//
|
||||
// Only stash this value if it's not empty
|
||||
if (!StartingDirectory().empty())
|
||||
{
|
||||
_lastStartingDirectoryPath = StartingDirectory();
|
||||
}
|
||||
StartingDirectory(L"");
|
||||
}
|
||||
else
|
||||
{
|
||||
// Restore the path we had previously cached as long as it wasn't empty
|
||||
// If it was empty, set the starting directory to %USERPROFILE%
|
||||
// (we need to set it to something non-empty otherwise we will automatically
|
||||
// disable the text box)
|
||||
if (_lastStartingDirectoryPath.empty())
|
||||
{
|
||||
StartingDirectory(L"%USERPROFILE%");
|
||||
}
|
||||
else
|
||||
{
|
||||
StartingDirectory(_lastStartingDirectoryPath);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void ProfilePageNavigationState::DeleteProfile()
|
||||
{
|
||||
auto deleteProfileArgs{ winrt::make_self<DeleteProfileEventArgs>(_Profile.Guid()) };
|
||||
_DeleteProfileHandlers(*this, *deleteProfileArgs);
|
||||
}
|
||||
|
||||
void ProfilePageNavigationState::CreateUnfocusedAppearance()
|
||||
{
|
||||
_Profile.CreateUnfocusedAppearance(_Schemes, _WindowRoot);
|
||||
}
|
||||
|
||||
void ProfilePageNavigationState::DeleteUnfocusedAppearance()
|
||||
{
|
||||
_Profile.DeleteUnfocusedAppearance();
|
||||
}
|
||||
|
||||
Profiles::Profiles() :
|
||||
_previewControl{ Control::TermControl(Model::TerminalSettings{}, nullptr, make<PreviewConnection>()) }
|
||||
{
|
||||
InitializeComponent();
|
||||
|
||||
INITIALIZE_BINDABLE_ENUM_SETTING(AntiAliasingMode, TextAntialiasingMode, winrt::Microsoft::Terminal::Control::TextAntialiasingMode, L"Profile_AntialiasingMode", L"Content");
|
||||
INITIALIZE_BINDABLE_ENUM_SETTING_REVERSE_ORDER(CloseOnExitMode, CloseOnExitMode, winrt::Microsoft::Terminal::Settings::Model::CloseOnExitMode, L"Profile_CloseOnExit", L"Content");
|
||||
INITIALIZE_BINDABLE_ENUM_SETTING(ScrollState, ScrollbarState, winrt::Microsoft::Terminal::Control::ScrollbarState, L"Profile_ScrollbarVisibility", L"Content");
|
||||
|
||||
const auto startingDirCheckboxTooltip{ ToolTipService::GetToolTip(StartingDirectoryUseParentCheckbox()) };
|
||||
Automation::AutomationProperties::SetFullDescription(StartingDirectoryUseParentCheckbox(), unbox_value<hstring>(startingDirCheckboxTooltip));
|
||||
|
||||
@@ -418,16 +38,17 @@ namespace winrt::Microsoft::Terminal::Settings::Editor::implementation
|
||||
|
||||
void Profiles::OnNavigatedTo(const NavigationEventArgs& e)
|
||||
{
|
||||
_State = e.Parameter().as<Editor::ProfilePageNavigationState>();
|
||||
auto state{ e.Parameter().as<Editor::ProfilePageNavigationState>() };
|
||||
_Profile = state.Profile();
|
||||
|
||||
// generate the font list, if we don't have one
|
||||
if (!_State.Profile().CompleteFontList() || !_State.Profile().MonospaceFontList())
|
||||
if (!ProfileViewModel::CompleteFontList() || !ProfileViewModel::MonospaceFontList())
|
||||
{
|
||||
ProfileViewModel::UpdateFontList();
|
||||
}
|
||||
|
||||
// Check the use parent directory box if the starting directory is empty
|
||||
if (_State.Profile().StartingDirectory().empty())
|
||||
if (_Profile.StartingDirectory().empty())
|
||||
{
|
||||
StartingDirectoryUseParentCheckbox().IsChecked(true);
|
||||
}
|
||||
@@ -435,7 +56,7 @@ namespace winrt::Microsoft::Terminal::Settings::Editor::implementation
|
||||
// Subscribe to some changes in the view model
|
||||
// These changes should force us to update our own set of "Current<Setting>" members,
|
||||
// and propagate those changes to the UI
|
||||
_ViewModelChangedRevoker = _State.Profile().PropertyChanged(winrt::auto_revoke, [=](auto&&, const PropertyChangedEventArgs& args) {
|
||||
_ViewModelChangedRevoker = _Profile.PropertyChanged(winrt::auto_revoke, [=](auto&&, const PropertyChangedEventArgs& args) {
|
||||
const auto settingName{ args.PropertyName() };
|
||||
if (settingName == L"AntialiasingMode")
|
||||
{
|
||||
@@ -453,23 +74,23 @@ namespace winrt::Microsoft::Terminal::Settings::Editor::implementation
|
||||
{
|
||||
_PropertyChangedHandlers(*this, PropertyChangedEventArgs{ L"CurrentScrollState" });
|
||||
}
|
||||
_previewControl.UpdateControlSettings(_State.Profile().TermSettings());
|
||||
_previewControl.UpdateControlSettings(_Profile.TermSettings());
|
||||
});
|
||||
|
||||
// The Appearances object handles updating the values in the settings UI, but
|
||||
// we still need to listen to the changes here just to update the preview control
|
||||
_AppearanceViewModelChangedRevoker = _State.Profile().DefaultAppearance().PropertyChanged(winrt::auto_revoke, [=](auto&&, const PropertyChangedEventArgs& /*args*/) {
|
||||
_previewControl.UpdateControlSettings(_State.Profile().TermSettings());
|
||||
_AppearanceViewModelChangedRevoker = _Profile.DefaultAppearance().PropertyChanged(winrt::auto_revoke, [=](auto&&, const PropertyChangedEventArgs& /*args*/) {
|
||||
_previewControl.UpdateControlSettings(_Profile.TermSettings());
|
||||
});
|
||||
|
||||
// Navigate to the pivot in the provided navigation state
|
||||
ProfilesPivot().SelectedIndex(static_cast<int>(_State.LastActivePivot()));
|
||||
ProfilesPivot().SelectedIndex(static_cast<int>(ProfileViewModel::LastActivePivot()));
|
||||
|
||||
// There is a possibility that the control has not fully initialized yet,
|
||||
// so wait for it to initialize before updating the settings (so we know
|
||||
// that the renderer is set up)
|
||||
_previewControl.Initialized([&](auto&& /*s*/, auto&& /*e*/) {
|
||||
_previewControl.UpdateControlSettings(_State.Profile().TermSettings());
|
||||
_previewControl.UpdateControlSettings(_Profile.TermSettings());
|
||||
});
|
||||
}
|
||||
|
||||
@@ -479,57 +100,30 @@ namespace winrt::Microsoft::Terminal::Settings::Editor::implementation
|
||||
_AppearanceViewModelChangedRevoker.revoke();
|
||||
}
|
||||
|
||||
bool Profiles::IsBellStyleFlagSet(const uint32_t flag)
|
||||
{
|
||||
return (WI_EnumValue(_State.Profile().BellStyle()) & flag) == flag;
|
||||
}
|
||||
|
||||
void Profiles::SetBellStyleAudible(winrt::Windows::Foundation::IReference<bool> on)
|
||||
{
|
||||
auto currentStyle = State().Profile().BellStyle();
|
||||
WI_UpdateFlag(currentStyle, Model::BellStyle::Audible, winrt::unbox_value<bool>(on));
|
||||
State().Profile().BellStyle(currentStyle);
|
||||
}
|
||||
|
||||
void Profiles::SetBellStyleWindow(winrt::Windows::Foundation::IReference<bool> on)
|
||||
{
|
||||
auto currentStyle = State().Profile().BellStyle();
|
||||
WI_UpdateFlag(currentStyle, Model::BellStyle::Window, winrt::unbox_value<bool>(on));
|
||||
State().Profile().BellStyle(currentStyle);
|
||||
}
|
||||
|
||||
void Profiles::SetBellStyleTaskbar(winrt::Windows::Foundation::IReference<bool> on)
|
||||
{
|
||||
auto currentStyle = State().Profile().BellStyle();
|
||||
WI_UpdateFlag(currentStyle, Model::BellStyle::Taskbar, winrt::unbox_value<bool>(on));
|
||||
State().Profile().BellStyle(currentStyle);
|
||||
}
|
||||
|
||||
void Profiles::DeleteConfirmation_Click(IInspectable const& /*sender*/, RoutedEventArgs const& /*e*/)
|
||||
{
|
||||
auto state{ winrt::get_self<ProfilePageNavigationState>(_State) };
|
||||
state->DeleteProfile();
|
||||
winrt::get_self<ProfileViewModel>(_Profile)->DeleteProfile();
|
||||
}
|
||||
|
||||
void Profiles::CreateUnfocusedAppearance_Click(IInspectable const& /*sender*/, RoutedEventArgs const& /*e*/)
|
||||
{
|
||||
_State.CreateUnfocusedAppearance();
|
||||
_Profile.CreateUnfocusedAppearance();
|
||||
}
|
||||
|
||||
void Profiles::DeleteUnfocusedAppearance_Click(IInspectable const& /*sender*/, RoutedEventArgs const& /*e*/)
|
||||
{
|
||||
_State.DeleteUnfocusedAppearance();
|
||||
_Profile.DeleteUnfocusedAppearance();
|
||||
}
|
||||
|
||||
fire_and_forget Profiles::Icon_Click(IInspectable const&, RoutedEventArgs const&)
|
||||
{
|
||||
auto lifetime = get_strong();
|
||||
|
||||
const auto parentHwnd{ reinterpret_cast<HWND>(_State.WindowRoot().GetHostingWindow()) };
|
||||
const auto parentHwnd{ reinterpret_cast<HWND>(winrt::get_self<ProfileViewModel>(_Profile)->WindowRoot().GetHostingWindow()) };
|
||||
auto file = co_await OpenImagePicker(parentHwnd);
|
||||
if (!file.empty())
|
||||
{
|
||||
_State.Profile().Icon(file);
|
||||
_Profile.Icon(file);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -543,7 +137,7 @@ namespace winrt::Microsoft::Terminal::Settings::Editor::implementation
|
||||
};
|
||||
|
||||
static constexpr winrt::guid clientGuidExecutables{ 0x2E7E4331, 0x0800, 0x48E6, { 0xB0, 0x17, 0xA1, 0x4C, 0xD8, 0x73, 0xDD, 0x58 } };
|
||||
const auto parentHwnd{ reinterpret_cast<HWND>(_State.WindowRoot().GetHostingWindow()) };
|
||||
const auto parentHwnd{ reinterpret_cast<HWND>(winrt::get_self<ProfileViewModel>(_Profile)->WindowRoot().GetHostingWindow()) };
|
||||
auto path = co_await OpenFilePicker(parentHwnd, [](auto&& dialog) {
|
||||
THROW_IF_FAILED(dialog->SetClientGuid(clientGuidExecutables));
|
||||
try
|
||||
@@ -559,14 +153,14 @@ namespace winrt::Microsoft::Terminal::Settings::Editor::implementation
|
||||
|
||||
if (!path.empty())
|
||||
{
|
||||
_State.Profile().Commandline(path);
|
||||
_Profile.Commandline(path);
|
||||
}
|
||||
}
|
||||
|
||||
fire_and_forget Profiles::StartingDirectory_Click(IInspectable const&, RoutedEventArgs const&)
|
||||
{
|
||||
auto lifetime = get_strong();
|
||||
const auto parentHwnd{ reinterpret_cast<HWND>(_State.WindowRoot().GetHostingWindow()) };
|
||||
const auto parentHwnd{ reinterpret_cast<HWND>(winrt::get_self<ProfileViewModel>(_Profile)->WindowRoot().GetHostingWindow()) };
|
||||
auto folder = co_await OpenFilePicker(parentHwnd, [](auto&& dialog) {
|
||||
static constexpr winrt::guid clientGuidFolderPicker{ 0xAADAA433, 0xB04D, 0x4BAE, { 0xB1, 0xEA, 0x1E, 0x6C, 0xD1, 0xCD, 0xA6, 0x8B } };
|
||||
THROW_IF_FAILED(dialog->SetClientGuid(clientGuidFolderPicker));
|
||||
@@ -584,13 +178,13 @@ namespace winrt::Microsoft::Terminal::Settings::Editor::implementation
|
||||
|
||||
if (!folder.empty())
|
||||
{
|
||||
_State.Profile().StartingDirectory(folder);
|
||||
_Profile.StartingDirectory(folder);
|
||||
}
|
||||
}
|
||||
|
||||
void Profiles::Pivot_SelectionChanged(Windows::Foundation::IInspectable const& /*sender*/,
|
||||
RoutedEventArgs const& /*e*/)
|
||||
{
|
||||
_State.LastActivePivot(static_cast<Editor::ProfilesPivots>(ProfilesPivot().SelectedIndex()));
|
||||
ProfileViewModel::LastActivePivot(static_cast<Editor::ProfilesPivots>(ProfilesPivot().SelectedIndex()));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -5,143 +5,25 @@
|
||||
|
||||
#include "Profiles.g.h"
|
||||
#include "ProfilePageNavigationState.g.h"
|
||||
#include "DeleteProfileEventArgs.g.h"
|
||||
#include "ProfileViewModel.g.h"
|
||||
#include "ProfileViewModel.h"
|
||||
#include "Utils.h"
|
||||
#include "ViewModelHelpers.h"
|
||||
#include "Appearances.h"
|
||||
|
||||
namespace winrt::Microsoft::Terminal::Settings::Editor::implementation
|
||||
{
|
||||
struct ProfileViewModel : ProfileViewModelT<ProfileViewModel>, ViewModelHelper<ProfileViewModel>
|
||||
{
|
||||
public:
|
||||
ProfileViewModel(const Model::Profile& profile, const Model::CascadiaSettings& settings);
|
||||
|
||||
Model::TerminalSettings TermSettings() const;
|
||||
|
||||
void SetAcrylicOpacityPercentageValue(double value)
|
||||
{
|
||||
Opacity(winrt::Microsoft::Terminal::Settings::Editor::Converters::PercentageValueToPercentage(value));
|
||||
|
||||
// GH#11372: If we're on Windows 10, and someone wants opacity, then
|
||||
// we'll turn acrylic on for them. Opacity doesn't work without
|
||||
// acrylic on Windows 10.
|
||||
//
|
||||
// BODGY: CascadiaSettings's function IsDefaultTerminalAvailable
|
||||
// is basically a "are we on Windows 11" check, because defterm
|
||||
// only works on Win11. So we'll use that.
|
||||
//
|
||||
// Remove when we can remove the rest of GH#11285
|
||||
if (value < 100.0 &&
|
||||
!winrt::Microsoft::Terminal::Settings::Model::CascadiaSettings::IsDefaultTerminalAvailable())
|
||||
{
|
||||
UseAcrylic(true);
|
||||
}
|
||||
};
|
||||
|
||||
void SetPadding(double value)
|
||||
{
|
||||
Padding(to_hstring(value));
|
||||
}
|
||||
|
||||
// starting directory
|
||||
bool UseParentProcessDirectory();
|
||||
void UseParentProcessDirectory(const bool useParent);
|
||||
bool UseCustomStartingDirectory();
|
||||
|
||||
// font face
|
||||
static void UpdateFontList() noexcept;
|
||||
Windows::Foundation::Collections::IObservableVector<Editor::Font> CompleteFontList() const noexcept;
|
||||
Windows::Foundation::Collections::IObservableVector<Editor::Font> MonospaceFontList() const noexcept;
|
||||
|
||||
// general profile knowledge
|
||||
winrt::guid OriginalProfileGuid() const noexcept;
|
||||
bool CanDeleteProfile() const;
|
||||
Editor::AppearanceViewModel DefaultAppearance();
|
||||
Editor::AppearanceViewModel UnfocusedAppearance();
|
||||
bool HasUnfocusedAppearance();
|
||||
bool EditableUnfocusedAppearance() const noexcept;
|
||||
bool ShowUnfocusedAppearance();
|
||||
void CreateUnfocusedAppearance(const Windows::Foundation::Collections::IMapView<hstring, Model::ColorScheme>& schemes,
|
||||
const IHostedInWindow& windowRoot);
|
||||
void DeleteUnfocusedAppearance();
|
||||
bool AtlasEngineAvailable() const noexcept;
|
||||
|
||||
WINRT_PROPERTY(bool, IsBaseLayer, false);
|
||||
|
||||
PERMANENT_OBSERVABLE_PROJECTED_SETTING(_profile, Guid);
|
||||
PERMANENT_OBSERVABLE_PROJECTED_SETTING(_profile, ConnectionType);
|
||||
OBSERVABLE_PROJECTED_SETTING(_profile, Name);
|
||||
OBSERVABLE_PROJECTED_SETTING(_profile, Source);
|
||||
OBSERVABLE_PROJECTED_SETTING(_profile, Hidden);
|
||||
OBSERVABLE_PROJECTED_SETTING(_profile, Icon);
|
||||
OBSERVABLE_PROJECTED_SETTING(_profile, CloseOnExit);
|
||||
OBSERVABLE_PROJECTED_SETTING(_profile, TabTitle);
|
||||
OBSERVABLE_PROJECTED_SETTING(_profile, TabColor);
|
||||
OBSERVABLE_PROJECTED_SETTING(_profile, SuppressApplicationTitle);
|
||||
OBSERVABLE_PROJECTED_SETTING(_profile, UseAcrylic);
|
||||
OBSERVABLE_PROJECTED_SETTING(_profile, ScrollState);
|
||||
OBSERVABLE_PROJECTED_SETTING(_profile, Padding);
|
||||
OBSERVABLE_PROJECTED_SETTING(_profile, Commandline);
|
||||
OBSERVABLE_PROJECTED_SETTING(_profile, StartingDirectory);
|
||||
OBSERVABLE_PROJECTED_SETTING(_profile, AntialiasingMode);
|
||||
OBSERVABLE_PROJECTED_SETTING(_profile.DefaultAppearance(), Foreground);
|
||||
OBSERVABLE_PROJECTED_SETTING(_profile.DefaultAppearance(), Background);
|
||||
OBSERVABLE_PROJECTED_SETTING(_profile.DefaultAppearance(), SelectionBackground);
|
||||
OBSERVABLE_PROJECTED_SETTING(_profile.DefaultAppearance(), CursorColor);
|
||||
OBSERVABLE_PROJECTED_SETTING(_profile.DefaultAppearance(), Opacity);
|
||||
OBSERVABLE_PROJECTED_SETTING(_profile, HistorySize);
|
||||
OBSERVABLE_PROJECTED_SETTING(_profile, SnapOnInput);
|
||||
OBSERVABLE_PROJECTED_SETTING(_profile, AltGrAliasing);
|
||||
OBSERVABLE_PROJECTED_SETTING(_profile, BellStyle);
|
||||
OBSERVABLE_PROJECTED_SETTING(_profile, UseAtlasEngine);
|
||||
|
||||
private:
|
||||
Model::Profile _profile;
|
||||
winrt::guid _originalProfileGuid;
|
||||
winrt::hstring _lastBgImagePath;
|
||||
winrt::hstring _lastStartingDirectoryPath;
|
||||
Editor::AppearanceViewModel _defaultAppearanceViewModel;
|
||||
|
||||
static Windows::Foundation::Collections::IObservableVector<Editor::Font> _MonospaceFontList;
|
||||
static Windows::Foundation::Collections::IObservableVector<Editor::Font> _FontList;
|
||||
|
||||
static Editor::Font _GetFont(com_ptr<IDWriteLocalizedStrings> localizedFamilyNames);
|
||||
|
||||
Model::CascadiaSettings _appSettings;
|
||||
Editor::AppearanceViewModel _unfocusedAppearanceViewModel;
|
||||
};
|
||||
|
||||
struct DeleteProfileEventArgs :
|
||||
public DeleteProfileEventArgsT<DeleteProfileEventArgs>
|
||||
{
|
||||
public:
|
||||
DeleteProfileEventArgs(guid profileGuid) :
|
||||
_ProfileGuid(profileGuid) {}
|
||||
|
||||
guid ProfileGuid() const noexcept { return _ProfileGuid; }
|
||||
|
||||
private:
|
||||
guid _ProfileGuid{};
|
||||
};
|
||||
|
||||
struct ProfilePageNavigationState : ProfilePageNavigationStateT<ProfilePageNavigationState>
|
||||
{
|
||||
public:
|
||||
ProfilePageNavigationState(const Editor::ProfileViewModel& viewModel,
|
||||
const Windows::Foundation::Collections::IMapView<hstring, Model::ColorScheme>& schemes,
|
||||
const Editor::ProfilePageNavigationState& lastState,
|
||||
const IHostedInWindow& windowRoot) :
|
||||
_Profile{ viewModel },
|
||||
_Schemes{ schemes },
|
||||
_WindowRoot{ windowRoot }
|
||||
_Profile{ viewModel }
|
||||
{
|
||||
// If there was a previous nav state copy the selected pivot from it.
|
||||
if (lastState)
|
||||
{
|
||||
_LastActivePivot = lastState.LastActivePivot();
|
||||
}
|
||||
auto profile{ winrt::get_self<ProfileViewModel>(viewModel) };
|
||||
profile->Schemes(schemes);
|
||||
profile->WindowRoot(windowRoot);
|
||||
|
||||
viewModel.DefaultAppearance().Schemes(schemes);
|
||||
viewModel.DefaultAppearance().WindowRoot(windowRoot);
|
||||
|
||||
@@ -151,20 +33,7 @@ namespace winrt::Microsoft::Terminal::Settings::Editor::implementation
|
||||
viewModel.UnfocusedAppearance().WindowRoot(windowRoot);
|
||||
}
|
||||
}
|
||||
|
||||
void DeleteProfile();
|
||||
void CreateUnfocusedAppearance();
|
||||
void DeleteUnfocusedAppearance();
|
||||
|
||||
Windows::Foundation::Collections::IMapView<hstring, Model::ColorScheme> Schemes() { return _Schemes; }
|
||||
void Schemes(const Windows::Foundation::Collections::IMapView<hstring, Model::ColorScheme>& val) { _Schemes = val; }
|
||||
TYPED_EVENT(DeleteProfile, Editor::ProfilePageNavigationState, Editor::DeleteProfileEventArgs);
|
||||
WINRT_PROPERTY(IHostedInWindow, WindowRoot, nullptr);
|
||||
WINRT_PROPERTY(Editor::ProfilesPivots, LastActivePivot, Editor::ProfilesPivots::General);
|
||||
WINRT_PROPERTY(Editor::ProfileViewModel, Profile, nullptr);
|
||||
|
||||
private:
|
||||
Windows::Foundation::Collections::IMapView<hstring, Model::ColorScheme> _Schemes;
|
||||
};
|
||||
|
||||
struct Profiles : public HasScrollViewer<Profiles>, ProfilesT<Profiles>
|
||||
@@ -175,12 +44,6 @@ namespace winrt::Microsoft::Terminal::Settings::Editor::implementation
|
||||
void OnNavigatedTo(const Windows::UI::Xaml::Navigation::NavigationEventArgs& e);
|
||||
void OnNavigatedFrom(const Windows::UI::Xaml::Navigation::NavigationEventArgs& e);
|
||||
|
||||
// bell style bits
|
||||
bool IsBellStyleFlagSet(const uint32_t flag);
|
||||
void SetBellStyleAudible(winrt::Windows::Foundation::IReference<bool> on);
|
||||
void SetBellStyleWindow(winrt::Windows::Foundation::IReference<bool> on);
|
||||
void SetBellStyleTaskbar(winrt::Windows::Foundation::IReference<bool> on);
|
||||
|
||||
fire_and_forget Commandline_Click(Windows::Foundation::IInspectable const& sender, Windows::UI::Xaml::RoutedEventArgs const& e);
|
||||
fire_and_forget StartingDirectory_Click(Windows::Foundation::IInspectable const& sender, Windows::UI::Xaml::RoutedEventArgs const& e);
|
||||
fire_and_forget Icon_Click(Windows::Foundation::IInspectable const& sender, Windows::UI::Xaml::RoutedEventArgs const& e);
|
||||
@@ -191,10 +54,7 @@ namespace winrt::Microsoft::Terminal::Settings::Editor::implementation
|
||||
|
||||
WINRT_CALLBACK(PropertyChanged, Windows::UI::Xaml::Data::PropertyChangedEventHandler);
|
||||
|
||||
WINRT_PROPERTY(Editor::ProfilePageNavigationState, State, nullptr);
|
||||
GETSET_BINDABLE_ENUM_SETTING(AntiAliasingMode, Microsoft::Terminal::Control::TextAntialiasingMode, State().Profile, AntialiasingMode);
|
||||
GETSET_BINDABLE_ENUM_SETTING(CloseOnExitMode, Microsoft::Terminal::Settings::Model::CloseOnExitMode, State().Profile, CloseOnExit);
|
||||
GETSET_BINDABLE_ENUM_SETTING(ScrollState, Microsoft::Terminal::Control::ScrollbarState, State().Profile, ScrollState);
|
||||
WINRT_PROPERTY(Editor::ProfileViewModel, Profile, nullptr);
|
||||
|
||||
private:
|
||||
void _UpdateBIAlignmentControl(const int32_t val);
|
||||
|
||||
@@ -1,113 +1,20 @@
|
||||
// Copyright (c) Microsoft Corporation.
|
||||
// Licensed under the MIT license.
|
||||
|
||||
import "EnumEntry.idl";
|
||||
import "MainPage.idl";
|
||||
import "Appearances.idl";
|
||||
|
||||
#include "ViewModelHelpers.idl.h"
|
||||
|
||||
#define OBSERVABLE_PROJECTED_PROFILE_SETTING(Type, Name) \
|
||||
OBSERVABLE_PROJECTED_SETTING(Type, Name); \
|
||||
Object Name##OverrideSource { get; }
|
||||
import "ProfileViewModel.idl";
|
||||
|
||||
namespace Microsoft.Terminal.Settings.Editor
|
||||
{
|
||||
runtimeclass ProfileViewModel : Windows.UI.Xaml.Data.INotifyPropertyChanged
|
||||
{
|
||||
Windows.Foundation.Collections.IObservableVector<Font> CompleteFontList { get; };
|
||||
Windows.Foundation.Collections.IObservableVector<Font> MonospaceFontList { get; };
|
||||
Microsoft.Terminal.Settings.Model.TerminalSettings TermSettings { get; };
|
||||
|
||||
void SetAcrylicOpacityPercentageValue(Double value);
|
||||
void SetPadding(Double value);
|
||||
|
||||
Boolean CanDeleteProfile { get; };
|
||||
Boolean IsBaseLayer;
|
||||
Boolean UseParentProcessDirectory;
|
||||
Boolean UseCustomStartingDirectory { get; };
|
||||
AppearanceViewModel DefaultAppearance { get; };
|
||||
Guid OriginalProfileGuid { get; };
|
||||
Boolean HasUnfocusedAppearance { get; };
|
||||
Boolean EditableUnfocusedAppearance { get; };
|
||||
Boolean ShowUnfocusedAppearance { get; };
|
||||
AppearanceViewModel UnfocusedAppearance { get; };
|
||||
Boolean AtlasEngineAvailable { get; };
|
||||
|
||||
void CreateUnfocusedAppearance(Windows.Foundation.Collections.IMapView<String, Microsoft.Terminal.Settings.Model.ColorScheme> Schemes, IHostedInWindow WindowRoot);
|
||||
void DeleteUnfocusedAppearance();
|
||||
|
||||
OBSERVABLE_PROJECTED_PROFILE_SETTING(String, Name);
|
||||
PERMANENT_OBSERVABLE_PROJECTED_SETTING(Guid, Guid);
|
||||
OBSERVABLE_PROJECTED_PROFILE_SETTING(String, Source);
|
||||
PERMANENT_OBSERVABLE_PROJECTED_SETTING(Guid, ConnectionType);
|
||||
OBSERVABLE_PROJECTED_PROFILE_SETTING(Boolean, Hidden);
|
||||
OBSERVABLE_PROJECTED_PROFILE_SETTING(String, Icon);
|
||||
OBSERVABLE_PROJECTED_PROFILE_SETTING(Microsoft.Terminal.Settings.Model.CloseOnExitMode, CloseOnExit);
|
||||
OBSERVABLE_PROJECTED_PROFILE_SETTING(String, TabTitle);
|
||||
OBSERVABLE_PROJECTED_PROFILE_SETTING(Windows.Foundation.IReference<Microsoft.Terminal.Core.Color>, TabColor);
|
||||
OBSERVABLE_PROJECTED_PROFILE_SETTING(Boolean, SuppressApplicationTitle);
|
||||
OBSERVABLE_PROJECTED_PROFILE_SETTING(Boolean, UseAcrylic);
|
||||
OBSERVABLE_PROJECTED_PROFILE_SETTING(Double, Opacity);
|
||||
OBSERVABLE_PROJECTED_PROFILE_SETTING(Microsoft.Terminal.Control.ScrollbarState, ScrollState);
|
||||
OBSERVABLE_PROJECTED_PROFILE_SETTING(String, Padding);
|
||||
OBSERVABLE_PROJECTED_PROFILE_SETTING(String, Commandline);
|
||||
OBSERVABLE_PROJECTED_PROFILE_SETTING(String, StartingDirectory);
|
||||
OBSERVABLE_PROJECTED_PROFILE_SETTING(Microsoft.Terminal.Control.TextAntialiasingMode, AntialiasingMode);
|
||||
OBSERVABLE_PROJECTED_PROFILE_SETTING(Windows.Foundation.IReference<Microsoft.Terminal.Core.Color>, Foreground);
|
||||
OBSERVABLE_PROJECTED_PROFILE_SETTING(Windows.Foundation.IReference<Microsoft.Terminal.Core.Color>, Background);
|
||||
OBSERVABLE_PROJECTED_PROFILE_SETTING(Windows.Foundation.IReference<Microsoft.Terminal.Core.Color>, SelectionBackground);
|
||||
OBSERVABLE_PROJECTED_PROFILE_SETTING(Windows.Foundation.IReference<Microsoft.Terminal.Core.Color>, CursorColor);
|
||||
OBSERVABLE_PROJECTED_PROFILE_SETTING(Int32, HistorySize);
|
||||
OBSERVABLE_PROJECTED_PROFILE_SETTING(Boolean, SnapOnInput);
|
||||
OBSERVABLE_PROJECTED_PROFILE_SETTING(Boolean, AltGrAliasing);
|
||||
OBSERVABLE_PROJECTED_PROFILE_SETTING(Microsoft.Terminal.Settings.Model.BellStyle, BellStyle);
|
||||
OBSERVABLE_PROJECTED_PROFILE_SETTING(Boolean, UseAtlasEngine);
|
||||
}
|
||||
|
||||
runtimeclass DeleteProfileEventArgs
|
||||
{
|
||||
Guid ProfileGuid { get; };
|
||||
}
|
||||
|
||||
enum ProfilesPivots
|
||||
{
|
||||
General = 0,
|
||||
Appearance = 1,
|
||||
Advanced = 2
|
||||
};
|
||||
|
||||
runtimeclass ProfilePageNavigationState
|
||||
{
|
||||
IHostedInWindow WindowRoot; // necessary to send the right HWND into the file picker dialogs.
|
||||
|
||||
ProfileViewModel Profile;
|
||||
ProfilesPivots LastActivePivot;
|
||||
|
||||
void CreateUnfocusedAppearance();
|
||||
void DeleteUnfocusedAppearance();
|
||||
|
||||
event Windows.Foundation.TypedEventHandler<ProfilePageNavigationState, DeleteProfileEventArgs> DeleteProfile;
|
||||
ProfileViewModel Profile { get; };
|
||||
};
|
||||
|
||||
[default_interface] runtimeclass Profiles : Windows.UI.Xaml.Controls.Page, Windows.UI.Xaml.Data.INotifyPropertyChanged
|
||||
{
|
||||
Profiles();
|
||||
ProfilePageNavigationState State { get; };
|
||||
|
||||
Boolean IsBellStyleFlagSet(UInt32 flag);
|
||||
void SetBellStyleAudible(Windows.Foundation.IReference<Boolean> on);
|
||||
void SetBellStyleWindow(Windows.Foundation.IReference<Boolean> on);
|
||||
void SetBellStyleTaskbar(Windows.Foundation.IReference<Boolean> on);
|
||||
|
||||
IInspectable CurrentAntiAliasingMode;
|
||||
Windows.Foundation.Collections.IObservableVector<Microsoft.Terminal.Settings.Editor.EnumEntry> AntiAliasingModeList { get; };
|
||||
|
||||
IInspectable CurrentCloseOnExitMode;
|
||||
Windows.Foundation.Collections.IObservableVector<Microsoft.Terminal.Settings.Editor.EnumEntry> CloseOnExitModeList { get; };
|
||||
|
||||
IInspectable CurrentScrollState;
|
||||
Windows.Foundation.Collections.IObservableVector<Microsoft.Terminal.Settings.Editor.EnumEntry> ScrollStateList { get; };
|
||||
ProfileViewModel Profile { get; };
|
||||
|
||||
Windows.UI.Xaml.Controls.Slider OpacitySlider { get; };
|
||||
}
|
||||
|
||||
@@ -47,7 +47,7 @@
|
||||
Grid.Row="0"
|
||||
Margin="{StaticResource StandardIndentMargin}"
|
||||
Style="{StaticResource DisclaimerStyle}"
|
||||
Visibility="{x:Bind State.Profile.IsBaseLayer}" />
|
||||
Visibility="{x:Bind Profile.IsBaseLayer}" />
|
||||
|
||||
<Pivot x:Name="ProfilesPivot"
|
||||
Grid.Row="1"
|
||||
@@ -67,24 +67,24 @@
|
||||
-->
|
||||
<local:SettingContainer x:Uid="Profile_Name"
|
||||
Margin="0,0,0,24"
|
||||
Visibility="{x:Bind local:Converters.InvertedBooleanToVisibility(State.Profile.IsBaseLayer), Mode=OneWay}">
|
||||
Visibility="{x:Bind local:Converters.InvertedBooleanToVisibility(Profile.IsBaseLayer), Mode=OneWay}">
|
||||
<TextBox Style="{StaticResource TextBoxSettingStyle}"
|
||||
Text="{x:Bind State.Profile.Name, Mode=TwoWay}" />
|
||||
Text="{x:Bind Profile.Name, Mode=TwoWay}" />
|
||||
</local:SettingContainer>
|
||||
|
||||
<!-- Commandline -->
|
||||
<local:SettingContainer x:Name="CommandlineContainer"
|
||||
x:Uid="Profile_Commandline"
|
||||
Margin="0,0,0,24"
|
||||
ClearSettingValue="{x:Bind State.Profile.ClearCommandline}"
|
||||
HasSettingValue="{x:Bind State.Profile.HasCommandline, Mode=OneWay}"
|
||||
SettingOverrideSource="{x:Bind State.Profile.CommandlineOverrideSource, Mode=OneWay}"
|
||||
Visibility="{x:Bind local:Converters.InvertedBooleanToVisibility(State.Profile.IsBaseLayer), Mode=OneWay}">
|
||||
ClearSettingValue="{x:Bind Profile.ClearCommandline}"
|
||||
HasSettingValue="{x:Bind Profile.HasCommandline, Mode=OneWay}"
|
||||
SettingOverrideSource="{x:Bind Profile.CommandlineOverrideSource, Mode=OneWay}"
|
||||
Visibility="{x:Bind local:Converters.InvertedBooleanToVisibility(Profile.IsBaseLayer), Mode=OneWay}">
|
||||
<StackPanel Orientation="Horizontal">
|
||||
<TextBox x:Uid="Profile_CommandlineBox"
|
||||
IsSpellCheckEnabled="False"
|
||||
Style="{StaticResource TextBoxSettingStyle}"
|
||||
Text="{x:Bind State.Profile.Commandline, Mode=TwoWay}" />
|
||||
Text="{x:Bind Profile.Commandline, Mode=TwoWay}" />
|
||||
<Button x:Uid="Profile_CommandlineBrowse"
|
||||
Click="Commandline_Click"
|
||||
Style="{StaticResource BrowseButtonStyle}" />
|
||||
@@ -95,39 +95,39 @@
|
||||
<local:SettingContainer x:Name="StartingDirectoryContainer"
|
||||
x:Uid="Profile_StartingDirectory"
|
||||
Margin="0"
|
||||
ClearSettingValue="{x:Bind State.Profile.ClearStartingDirectory}"
|
||||
HasSettingValue="{x:Bind State.Profile.HasStartingDirectory, Mode=OneWay}"
|
||||
SettingOverrideSource="{x:Bind State.Profile.StartingDirectoryOverrideSource, Mode=OneWay}">
|
||||
ClearSettingValue="{x:Bind Profile.ClearStartingDirectory}"
|
||||
HasSettingValue="{x:Bind Profile.HasStartingDirectory, Mode=OneWay}"
|
||||
SettingOverrideSource="{x:Bind Profile.StartingDirectoryOverrideSource, Mode=OneWay}">
|
||||
<StackPanel Orientation="Vertical">
|
||||
<StackPanel Orientation="Horizontal">
|
||||
<TextBox x:Uid="Profile_StartingDirectoryBox"
|
||||
IsEnabled="{x:Bind State.Profile.UseCustomStartingDirectory, Mode=OneWay}"
|
||||
IsEnabled="{x:Bind Profile.UseCustomStartingDirectory, Mode=OneWay}"
|
||||
IsSpellCheckEnabled="False"
|
||||
Style="{StaticResource TextBoxSettingStyle}"
|
||||
Text="{x:Bind State.Profile.StartingDirectory, Mode=TwoWay}" />
|
||||
Text="{x:Bind Profile.StartingDirectory, Mode=TwoWay}" />
|
||||
<Button x:Name="StartingDirectoryBrowse"
|
||||
x:Uid="Profile_StartingDirectoryBrowse"
|
||||
Click="StartingDirectory_Click"
|
||||
IsEnabled="{x:Bind State.Profile.UseCustomStartingDirectory, Mode=OneWay}"
|
||||
IsEnabled="{x:Bind Profile.UseCustomStartingDirectory, Mode=OneWay}"
|
||||
Style="{StaticResource BrowseButtonStyle}" />
|
||||
</StackPanel>
|
||||
<CheckBox x:Name="StartingDirectoryUseParentCheckbox"
|
||||
x:Uid="Profile_StartingDirectoryUseParentCheckbox"
|
||||
IsChecked="{x:Bind State.Profile.UseParentProcessDirectory, Mode=TwoWay}" />
|
||||
IsChecked="{x:Bind Profile.UseParentProcessDirectory, Mode=TwoWay}" />
|
||||
</StackPanel>
|
||||
</local:SettingContainer>
|
||||
|
||||
<!-- Icon -->
|
||||
<local:SettingContainer x:Uid="Profile_Icon"
|
||||
ClearSettingValue="{x:Bind State.Profile.ClearIcon}"
|
||||
HasSettingValue="{x:Bind State.Profile.HasIcon, Mode=OneWay}"
|
||||
SettingOverrideSource="{x:Bind State.Profile.IconOverrideSource, Mode=OneWay}">
|
||||
ClearSettingValue="{x:Bind Profile.ClearIcon}"
|
||||
HasSettingValue="{x:Bind Profile.HasIcon, Mode=OneWay}"
|
||||
SettingOverrideSource="{x:Bind Profile.IconOverrideSource, Mode=OneWay}">
|
||||
<StackPanel Orientation="Horizontal">
|
||||
<TextBox x:Uid="Profile_IconBox"
|
||||
FontFamily="Segoe UI, Segoe MDL2 Assets"
|
||||
IsSpellCheckEnabled="False"
|
||||
Style="{StaticResource TextBoxSettingStyle}"
|
||||
Text="{x:Bind State.Profile.Icon, Mode=TwoWay}" />
|
||||
Text="{x:Bind Profile.Icon, Mode=TwoWay}" />
|
||||
<Button x:Uid="Profile_IconBrowse"
|
||||
Click="Icon_Click"
|
||||
Style="{StaticResource BrowseButtonStyle}" />
|
||||
@@ -136,24 +136,24 @@
|
||||
|
||||
<!-- Tab Title -->
|
||||
<local:SettingContainer x:Uid="Profile_TabTitle"
|
||||
ClearSettingValue="{x:Bind State.Profile.ClearTabTitle}"
|
||||
HasSettingValue="{x:Bind State.Profile.HasTabTitle, Mode=OneWay}"
|
||||
SettingOverrideSource="{x:Bind State.Profile.TabTitleOverrideSource, Mode=OneWay}">
|
||||
ClearSettingValue="{x:Bind Profile.ClearTabTitle}"
|
||||
HasSettingValue="{x:Bind Profile.HasTabTitle, Mode=OneWay}"
|
||||
SettingOverrideSource="{x:Bind Profile.TabTitleOverrideSource, Mode=OneWay}">
|
||||
<TextBox Style="{StaticResource TextBoxSettingStyle}"
|
||||
Text="{x:Bind State.Profile.TabTitle, Mode=TwoWay}" />
|
||||
Text="{x:Bind Profile.TabTitle, Mode=TwoWay}" />
|
||||
</local:SettingContainer>
|
||||
|
||||
<!-- Hidden -->
|
||||
<local:SettingContainer x:Uid="Profile_Hidden"
|
||||
Visibility="{x:Bind local:Converters.InvertedBooleanToVisibility(State.Profile.IsBaseLayer), Mode=OneWay}">
|
||||
<ToggleSwitch IsOn="{x:Bind State.Profile.Hidden, Mode=TwoWay}" />
|
||||
Visibility="{x:Bind local:Converters.InvertedBooleanToVisibility(Profile.IsBaseLayer), Mode=OneWay}">
|
||||
<ToggleSwitch IsOn="{x:Bind Profile.Hidden, Mode=TwoWay}" />
|
||||
</local:SettingContainer>
|
||||
|
||||
<!-- Delete Button -->
|
||||
<Button x:Name="DeleteButton"
|
||||
Margin="{StaticResource StandardControlMargin}"
|
||||
Style="{StaticResource DeleteButtonStyle}"
|
||||
Visibility="{x:Bind State.Profile.CanDeleteProfile}">
|
||||
Visibility="{x:Bind Profile.CanDeleteProfile}">
|
||||
<Button.Resources>
|
||||
<ResourceDictionary>
|
||||
<ResourceDictionary.ThemeDictionaries>
|
||||
@@ -238,8 +238,8 @@
|
||||
BorderBrush="{ThemeResource SystemControlForegroundBaseMediumLowBrush}"
|
||||
BorderThickness="1" />
|
||||
|
||||
<local:Appearances Appearance="{x:Bind State.Profile.DefaultAppearance, Mode=OneWay}"
|
||||
SourceProfile="{x:Bind State.Profile, Mode=OneWay}" />
|
||||
<local:Appearances Appearance="{x:Bind Profile.DefaultAppearance, Mode=OneWay}"
|
||||
SourceProfile="{x:Bind Profile, Mode=OneWay}" />
|
||||
|
||||
<!-- Grouping: Transparency -->
|
||||
<StackPanel Style="{StaticResource PivotStackStyle}">
|
||||
@@ -250,9 +250,9 @@
|
||||
<local:SettingContainer x:Name="OpacityContainer"
|
||||
x:Uid="Profile_Opacity"
|
||||
Margin="0"
|
||||
ClearSettingValue="{x:Bind State.Profile.ClearOpacity}"
|
||||
HasSettingValue="{x:Bind State.Profile.HasOpacity, Mode=OneWay}"
|
||||
SettingOverrideSource="{x:Bind State.Profile.OpacityOverrideSource, Mode=OneWay}">
|
||||
ClearSettingValue="{x:Bind Profile.ClearOpacity}"
|
||||
HasSettingValue="{x:Bind Profile.HasOpacity, Mode=OneWay}"
|
||||
SettingOverrideSource="{x:Bind Profile.OpacityOverrideSource, Mode=OneWay}">
|
||||
<StackPanel x:Name="OpacityControl">
|
||||
<Grid Style="{StaticResource CustomSliderControlGridStyle}">
|
||||
<Grid.ColumnDefinitions>
|
||||
@@ -261,7 +261,7 @@
|
||||
</Grid.ColumnDefinitions>
|
||||
<Slider x:Name="OpacitySlider"
|
||||
Grid.Column="0"
|
||||
Value="{x:Bind local:Converters.PercentageToPercentageValue(State.Profile.Opacity), BindBack=State.Profile.SetAcrylicOpacityPercentageValue, Mode=TwoWay}" />
|
||||
Value="{x:Bind local:Converters.PercentageToPercentageValue(Profile.Opacity), BindBack=Profile.SetAcrylicOpacityPercentageValue, Mode=TwoWay}" />
|
||||
<TextBlock Grid.Column="1"
|
||||
Style="{StaticResource SliderValueLabelStyle}"
|
||||
Text="{x:Bind local:Converters.AppendPercentageSign(OpacitySlider.Value), Mode=OneWay}" />
|
||||
@@ -272,11 +272,11 @@
|
||||
<!-- Use Acrylic -->
|
||||
<local:SettingContainer x:Uid="Profile_UseAcrylic"
|
||||
Margin="0"
|
||||
ClearSettingValue="{x:Bind State.Profile.ClearUseAcrylic}"
|
||||
HasSettingValue="{x:Bind State.Profile.HasUseAcrylic, Mode=OneWay}"
|
||||
SettingOverrideSource="{x:Bind State.Profile.UseAcrylicOverrideSource, Mode=OneWay}">
|
||||
ClearSettingValue="{x:Bind Profile.ClearUseAcrylic}"
|
||||
HasSettingValue="{x:Bind Profile.HasUseAcrylic, Mode=OneWay}"
|
||||
SettingOverrideSource="{x:Bind Profile.UseAcrylicOverrideSource, Mode=OneWay}">
|
||||
<ToggleSwitch x:Name="UseAcrylicToggleSwitch"
|
||||
IsOn="{x:Bind State.Profile.UseAcrylic, Mode=TwoWay}" />
|
||||
IsOn="{x:Bind Profile.UseAcrylic, Mode=TwoWay}" />
|
||||
</local:SettingContainer>
|
||||
|
||||
</StackPanel>
|
||||
@@ -289,9 +289,9 @@
|
||||
<!-- Padding -->
|
||||
<local:SettingContainer x:Uid="Profile_Padding"
|
||||
Margin="0"
|
||||
ClearSettingValue="{x:Bind State.Profile.ClearPadding}"
|
||||
HasSettingValue="{x:Bind State.Profile.HasPadding, Mode=OneWay}"
|
||||
SettingOverrideSource="{x:Bind State.Profile.PaddingOverrideSource, Mode=OneWay}">
|
||||
ClearSettingValue="{x:Bind Profile.ClearPadding}"
|
||||
HasSettingValue="{x:Bind Profile.HasPadding, Mode=OneWay}"
|
||||
SettingOverrideSource="{x:Bind Profile.PaddingOverrideSource, Mode=OneWay}">
|
||||
<Grid Style="{StaticResource CustomSliderControlGridStyle}">
|
||||
<Grid.ColumnDefinitions>
|
||||
<ColumnDefinition Width="*" />
|
||||
@@ -299,7 +299,7 @@
|
||||
</Grid.ColumnDefinitions>
|
||||
<Slider x:Name="PaddingSlider"
|
||||
Grid.Column="0"
|
||||
Value="{x:Bind local:Converters.MaxValueFromPaddingString(State.Profile.Padding), BindBack=State.Profile.SetPadding, Mode=TwoWay}" />
|
||||
Value="{x:Bind local:Converters.MaxValueFromPaddingString(Profile.Padding), BindBack=Profile.SetPadding, Mode=TwoWay}" />
|
||||
<TextBlock Grid.Column="1"
|
||||
Style="{StaticResource SliderValueLabelStyle}"
|
||||
Text="{Binding ElementName=PaddingSlider, Path=Value, Mode=OneWay}" />
|
||||
@@ -308,25 +308,25 @@
|
||||
|
||||
<!-- Scrollbar Visibility -->
|
||||
<local:SettingContainer x:Uid="Profile_ScrollbarVisibility"
|
||||
ClearSettingValue="{x:Bind State.Profile.ClearScrollState}"
|
||||
HasSettingValue="{x:Bind State.Profile.HasScrollState, Mode=OneWay}"
|
||||
SettingOverrideSource="{x:Bind State.Profile.ScrollStateOverrideSource, Mode=OneWay}">
|
||||
ClearSettingValue="{x:Bind Profile.ClearScrollState}"
|
||||
HasSettingValue="{x:Bind Profile.HasScrollState, Mode=OneWay}"
|
||||
SettingOverrideSource="{x:Bind Profile.ScrollStateOverrideSource, Mode=OneWay}">
|
||||
<muxc:RadioButtons AutomationProperties.AccessibilityView="Content"
|
||||
ItemTemplate="{StaticResource EnumRadioButtonTemplate}"
|
||||
ItemsSource="{x:Bind ScrollStateList, Mode=OneWay}"
|
||||
SelectedItem="{x:Bind CurrentScrollState, Mode=TwoWay}" />
|
||||
ItemsSource="{x:Bind Profile.ScrollStateList, Mode=OneWay}"
|
||||
SelectedItem="{x:Bind Profile.CurrentScrollState, Mode=TwoWay}" />
|
||||
</local:SettingContainer>
|
||||
</StackPanel>
|
||||
<StackPanel>
|
||||
<StackPanel Orientation="Horizontal"
|
||||
Visibility="{x:Bind State.Profile.EditableUnfocusedAppearance}">
|
||||
Visibility="{x:Bind Profile.EditableUnfocusedAppearance}">
|
||||
<TextBlock x:Uid="Profile_UnfocusedAppearanceTextBlock"
|
||||
Style="{StaticResource TitleTextBlockStyle}" />
|
||||
<Button x:Uid="Profile_CreateUnfocusedAppearanceButton"
|
||||
Margin="32,0,0,0"
|
||||
Click="CreateUnfocusedAppearance_Click"
|
||||
Style="{StaticResource BaseButtonStyle}"
|
||||
Visibility="{x:Bind local:Converters.InvertedBooleanToVisibility(State.Profile.HasUnfocusedAppearance), Mode=OneWay}">
|
||||
Visibility="{x:Bind local:Converters.InvertedBooleanToVisibility(Profile.HasUnfocusedAppearance), Mode=OneWay}">
|
||||
<Button.Content>
|
||||
<FontIcon FontSize="{StaticResource StandardIconSize}"
|
||||
Glyph="" />
|
||||
@@ -336,7 +336,7 @@
|
||||
Margin="32,0,0,0"
|
||||
Click="DeleteUnfocusedAppearance_Click"
|
||||
Style="{StaticResource BaseButtonStyle}"
|
||||
Visibility="{x:Bind State.Profile.HasUnfocusedAppearance, Mode=OneWay}">
|
||||
Visibility="{x:Bind Profile.HasUnfocusedAppearance, Mode=OneWay}">
|
||||
<Button.Content>
|
||||
<FontIcon FontSize="{StaticResource StandardIconSize}"
|
||||
Glyph="" />
|
||||
@@ -391,9 +391,9 @@
|
||||
</Button.Resources>
|
||||
</Button>
|
||||
</StackPanel>
|
||||
<local:Appearances Appearance="{x:Bind State.Profile.UnfocusedAppearance, Mode=OneWay}"
|
||||
SourceProfile="{x:Bind State.Profile, Mode=OneWay}"
|
||||
Visibility="{x:Bind State.Profile.ShowUnfocusedAppearance, Mode=OneWay}" />
|
||||
<local:Appearances Appearance="{x:Bind Profile.UnfocusedAppearance, Mode=OneWay}"
|
||||
SourceProfile="{x:Bind Profile, Mode=OneWay}"
|
||||
Visibility="{x:Bind Profile.ShowUnfocusedAppearance, Mode=OneWay}" />
|
||||
</StackPanel>
|
||||
</StackPanel>
|
||||
</ScrollViewer>
|
||||
@@ -406,85 +406,85 @@
|
||||
<!-- Suppress Application Title -->
|
||||
<local:SettingContainer x:Uid="Profile_SuppressApplicationTitle"
|
||||
Margin="0"
|
||||
ClearSettingValue="{x:Bind State.Profile.ClearSuppressApplicationTitle}"
|
||||
HasSettingValue="{x:Bind State.Profile.HasSuppressApplicationTitle, Mode=OneWay}"
|
||||
SettingOverrideSource="{x:Bind State.Profile.SuppressApplicationTitleOverrideSource, Mode=OneWay}">
|
||||
<ToggleSwitch IsOn="{x:Bind State.Profile.SuppressApplicationTitle, Mode=TwoWay}" />
|
||||
ClearSettingValue="{x:Bind Profile.ClearSuppressApplicationTitle}"
|
||||
HasSettingValue="{x:Bind Profile.HasSuppressApplicationTitle, Mode=OneWay}"
|
||||
SettingOverrideSource="{x:Bind Profile.SuppressApplicationTitleOverrideSource, Mode=OneWay}">
|
||||
<ToggleSwitch IsOn="{x:Bind Profile.SuppressApplicationTitle, Mode=TwoWay}" />
|
||||
</local:SettingContainer>
|
||||
|
||||
<!-- Antialiasing Mode -->
|
||||
<local:SettingContainer x:Uid="Profile_AntialiasingMode"
|
||||
ClearSettingValue="{x:Bind State.Profile.ClearAntialiasingMode}"
|
||||
HasSettingValue="{x:Bind State.Profile.HasAntialiasingMode, Mode=OneWay}"
|
||||
SettingOverrideSource="{x:Bind State.Profile.AntialiasingModeOverrideSource, Mode=OneWay}">
|
||||
ClearSettingValue="{x:Bind Profile.ClearAntialiasingMode}"
|
||||
HasSettingValue="{x:Bind Profile.HasAntialiasingMode, Mode=OneWay}"
|
||||
SettingOverrideSource="{x:Bind Profile.AntialiasingModeOverrideSource, Mode=OneWay}">
|
||||
<muxc:RadioButtons AutomationProperties.AccessibilityView="Content"
|
||||
ItemTemplate="{StaticResource EnumRadioButtonTemplate}"
|
||||
ItemsSource="{x:Bind AntiAliasingModeList, Mode=OneWay}"
|
||||
SelectedItem="{x:Bind CurrentAntiAliasingMode, Mode=TwoWay}" />
|
||||
ItemsSource="{x:Bind Profile.AntiAliasingModeList, Mode=OneWay}"
|
||||
SelectedItem="{x:Bind Profile.CurrentAntiAliasingMode, Mode=TwoWay}" />
|
||||
</local:SettingContainer>
|
||||
|
||||
<!-- AltGr Aliasing -->
|
||||
<local:SettingContainer x:Uid="Profile_AltGrAliasing"
|
||||
ClearSettingValue="{x:Bind State.Profile.ClearAltGrAliasing}"
|
||||
HasSettingValue="{x:Bind State.Profile.HasAltGrAliasing, Mode=OneWay}"
|
||||
SettingOverrideSource="{x:Bind State.Profile.AltGrAliasingOverrideSource, Mode=OneWay}">
|
||||
<ToggleSwitch IsOn="{x:Bind State.Profile.AltGrAliasing, Mode=TwoWay}" />
|
||||
ClearSettingValue="{x:Bind Profile.ClearAltGrAliasing}"
|
||||
HasSettingValue="{x:Bind Profile.HasAltGrAliasing, Mode=OneWay}"
|
||||
SettingOverrideSource="{x:Bind Profile.AltGrAliasingOverrideSource, Mode=OneWay}">
|
||||
<ToggleSwitch IsOn="{x:Bind Profile.AltGrAliasing, Mode=TwoWay}" />
|
||||
</local:SettingContainer>
|
||||
|
||||
<!-- Snap On Input -->
|
||||
<local:SettingContainer x:Uid="Profile_SnapOnInput"
|
||||
ClearSettingValue="{x:Bind State.Profile.ClearSnapOnInput}"
|
||||
HasSettingValue="{x:Bind State.Profile.HasSnapOnInput, Mode=OneWay}"
|
||||
SettingOverrideSource="{x:Bind State.Profile.SnapOnInputOverrideSource, Mode=OneWay}">
|
||||
<ToggleSwitch IsOn="{x:Bind State.Profile.SnapOnInput, Mode=TwoWay}" />
|
||||
ClearSettingValue="{x:Bind Profile.ClearSnapOnInput}"
|
||||
HasSettingValue="{x:Bind Profile.HasSnapOnInput, Mode=OneWay}"
|
||||
SettingOverrideSource="{x:Bind Profile.SnapOnInputOverrideSource, Mode=OneWay}">
|
||||
<ToggleSwitch IsOn="{x:Bind Profile.SnapOnInput, Mode=TwoWay}" />
|
||||
</local:SettingContainer>
|
||||
|
||||
<!-- History Size -->
|
||||
<local:SettingContainer x:Uid="Profile_HistorySize"
|
||||
ClearSettingValue="{x:Bind State.Profile.ClearHistorySize}"
|
||||
HasSettingValue="{x:Bind State.Profile.HasHistorySize, Mode=OneWay}"
|
||||
SettingOverrideSource="{x:Bind State.Profile.HistorySizeOverrideSource, Mode=OneWay}">
|
||||
ClearSettingValue="{x:Bind Profile.ClearHistorySize}"
|
||||
HasSettingValue="{x:Bind Profile.HasHistorySize, Mode=OneWay}"
|
||||
SettingOverrideSource="{x:Bind Profile.HistorySizeOverrideSource, Mode=OneWay}">
|
||||
<muxc:NumberBox x:Uid="Profile_HistorySizeBox"
|
||||
LargeChange="100"
|
||||
Minimum="0"
|
||||
SmallChange="10"
|
||||
Style="{StaticResource NumberBoxSettingStyle}"
|
||||
Value="{x:Bind State.Profile.HistorySize, Mode=TwoWay}" />
|
||||
Value="{x:Bind Profile.HistorySize, Mode=TwoWay}" />
|
||||
</local:SettingContainer>
|
||||
|
||||
<!-- Close On Exit -->
|
||||
<local:SettingContainer x:Uid="Profile_CloseOnExit"
|
||||
ClearSettingValue="{x:Bind State.Profile.ClearCloseOnExit}"
|
||||
HasSettingValue="{x:Bind State.Profile.HasCloseOnExit, Mode=OneWay}"
|
||||
SettingOverrideSource="{x:Bind State.Profile.CloseOnExitOverrideSource, Mode=OneWay}">
|
||||
ClearSettingValue="{x:Bind Profile.ClearCloseOnExit}"
|
||||
HasSettingValue="{x:Bind Profile.HasCloseOnExit, Mode=OneWay}"
|
||||
SettingOverrideSource="{x:Bind Profile.CloseOnExitOverrideSource, Mode=OneWay}">
|
||||
<muxc:RadioButtons AutomationProperties.AccessibilityView="Content"
|
||||
ItemTemplate="{StaticResource EnumRadioButtonTemplate}"
|
||||
ItemsSource="{x:Bind CloseOnExitModeList, Mode=OneWay}"
|
||||
SelectedItem="{x:Bind CurrentCloseOnExitMode, Mode=TwoWay}" />
|
||||
ItemsSource="{x:Bind Profile.CloseOnExitModeList, Mode=OneWay}"
|
||||
SelectedItem="{x:Bind Profile.CurrentCloseOnExitMode, Mode=TwoWay}" />
|
||||
</local:SettingContainer>
|
||||
|
||||
<!-- Bell Style -->
|
||||
<local:SettingContainer x:Uid="Profile_BellStyle"
|
||||
ClearSettingValue="{x:Bind State.Profile.ClearBellStyle}"
|
||||
HasSettingValue="{x:Bind State.Profile.HasBellStyle, Mode=OneWay}"
|
||||
SettingOverrideSource="{x:Bind State.Profile.BellStyleOverrideSource, Mode=OneWay}">
|
||||
ClearSettingValue="{x:Bind Profile.ClearBellStyle}"
|
||||
HasSettingValue="{x:Bind Profile.HasBellStyle, Mode=OneWay}"
|
||||
SettingOverrideSource="{x:Bind Profile.BellStyleOverrideSource, Mode=OneWay}">
|
||||
<StackPanel>
|
||||
<CheckBox x:Uid="Profile_BellStyleAudible"
|
||||
IsChecked="{x:Bind IsBellStyleFlagSet(1), BindBack=SetBellStyleAudible, Mode=TwoWay}" />
|
||||
IsChecked="{x:Bind Profile.IsBellStyleFlagSet(1), BindBack=Profile.SetBellStyleAudible, Mode=TwoWay}" />
|
||||
<CheckBox x:Uid="Profile_BellStyleWindow"
|
||||
IsChecked="{x:Bind IsBellStyleFlagSet(2), BindBack=SetBellStyleWindow, Mode=TwoWay}" />
|
||||
IsChecked="{x:Bind Profile.IsBellStyleFlagSet(2), BindBack=Profile.SetBellStyleWindow, Mode=TwoWay}" />
|
||||
<CheckBox x:Uid="Profile_BellStyleTaskbar"
|
||||
IsChecked="{x:Bind IsBellStyleFlagSet(4), BindBack=SetBellStyleTaskbar, Mode=TwoWay}" />
|
||||
IsChecked="{x:Bind Profile.IsBellStyleFlagSet(4), BindBack=Profile.SetBellStyleTaskbar, Mode=TwoWay}" />
|
||||
</StackPanel>
|
||||
</local:SettingContainer>
|
||||
|
||||
<!-- AtlasEngine -->
|
||||
<local:SettingContainer x:Uid="Profile_UseAtlasEngine"
|
||||
ClearSettingValue="{x:Bind State.Profile.ClearUseAtlasEngine}"
|
||||
HasSettingValue="{x:Bind State.Profile.HasUseAtlasEngine, Mode=OneWay}"
|
||||
SettingOverrideSource="{x:Bind State.Profile.UseAtlasEngineOverrideSource, Mode=OneWay}"
|
||||
Visibility="{x:Bind State.Profile.AtlasEngineAvailable}">
|
||||
<ToggleSwitch IsOn="{x:Bind State.Profile.UseAtlasEngine, Mode=TwoWay}" />
|
||||
ClearSettingValue="{x:Bind Profile.ClearUseAtlasEngine}"
|
||||
HasSettingValue="{x:Bind Profile.HasUseAtlasEngine, Mode=OneWay}"
|
||||
SettingOverrideSource="{x:Bind Profile.UseAtlasEngineOverrideSource, Mode=OneWay}"
|
||||
Visibility="{x:Bind Profile.AtlasEngineAvailable}">
|
||||
<ToggleSwitch IsOn="{x:Bind Profile.UseAtlasEngine, Mode=TwoWay}" />
|
||||
</local:SettingContainer>
|
||||
</StackPanel>
|
||||
</ScrollViewer>
|
||||
|
||||
@@ -49,29 +49,29 @@
|
||||
// of EnumEntries so that we may display all possible values of the given
|
||||
// enum type and its localized names. It also provides a getter and setter
|
||||
// for the setting we wish to bind to.
|
||||
#define GETSET_BINDABLE_ENUM_SETTING(name, enumType, settingsModelName, settingNameInModel) \
|
||||
public: \
|
||||
winrt::Windows::Foundation::Collections::IObservableVector<winrt::Microsoft::Terminal::Settings::Editor::EnumEntry> name##List() \
|
||||
{ \
|
||||
return _##name##List; \
|
||||
} \
|
||||
\
|
||||
winrt::Windows::Foundation::IInspectable Current##name() \
|
||||
{ \
|
||||
return winrt::box_value<winrt::Microsoft::Terminal::Settings::Editor::EnumEntry>(_##name##Map.Lookup(settingsModelName().settingNameInModel())); \
|
||||
} \
|
||||
\
|
||||
void Current##name(const winrt::Windows::Foundation::IInspectable& enumEntry) \
|
||||
{ \
|
||||
if (auto ee = enumEntry.try_as<winrt::Microsoft::Terminal::Settings::Editor::EnumEntry>()) \
|
||||
{ \
|
||||
auto setting = winrt::unbox_value<enumType>(ee.EnumValue()); \
|
||||
settingsModelName().settingNameInModel(setting); \
|
||||
} \
|
||||
} \
|
||||
\
|
||||
private: \
|
||||
winrt::Windows::Foundation::Collections::IObservableVector<winrt::Microsoft::Terminal::Settings::Editor::EnumEntry> _##name##List; \
|
||||
#define GETSET_BINDABLE_ENUM_SETTING(name, enumType, settingsModelName, settingNameInModel) \
|
||||
public: \
|
||||
winrt::Windows::Foundation::Collections::IObservableVector<winrt::Microsoft::Terminal::Settings::Editor::EnumEntry> name##List() \
|
||||
{ \
|
||||
return _##name##List; \
|
||||
} \
|
||||
\
|
||||
winrt::Windows::Foundation::IInspectable Current##name() \
|
||||
{ \
|
||||
return winrt::box_value<winrt::Microsoft::Terminal::Settings::Editor::EnumEntry>(_##name##Map.Lookup(settingsModelName.settingNameInModel())); \
|
||||
} \
|
||||
\
|
||||
void Current##name(const winrt::Windows::Foundation::IInspectable& enumEntry) \
|
||||
{ \
|
||||
if (auto ee = enumEntry.try_as<winrt::Microsoft::Terminal::Settings::Editor::EnumEntry>()) \
|
||||
{ \
|
||||
auto setting = winrt::unbox_value<enumType>(ee.EnumValue()); \
|
||||
settingsModelName.settingNameInModel(setting); \
|
||||
} \
|
||||
} \
|
||||
\
|
||||
private: \
|
||||
winrt::Windows::Foundation::Collections::IObservableVector<winrt::Microsoft::Terminal::Settings::Editor::EnumEntry> _##name##List; \
|
||||
winrt::Windows::Foundation::Collections::IMap<enumType, winrt::Microsoft::Terminal::Settings::Editor::EnumEntry> _##name##Map;
|
||||
|
||||
// This macro defines a dependency property for a WinRT class.
|
||||
|
||||
Reference in New Issue
Block a user