174 lines
7.1 KiB
C++
174 lines
7.1 KiB
C++
// Copyright (c) Microsoft Corporation.
|
|
// Licensed under the MIT license.
|
|
|
|
#include "pch.h"
|
|
#include "EnumEntry.h"
|
|
#include "GlobalAppearance.h"
|
|
#include "GlobalAppearance.g.cpp"
|
|
#include "GlobalAppearancePageNavigationState.g.cpp"
|
|
|
|
#include <LibraryResources.h>
|
|
|
|
using namespace winrt;
|
|
using namespace winrt::Windows::UI::Xaml;
|
|
using namespace winrt::Windows::UI::Xaml::Navigation;
|
|
using namespace winrt::Windows::UI::Xaml::Controls;
|
|
using namespace winrt::Microsoft::Terminal::Settings::Model;
|
|
using namespace winrt::Windows::Foundation::Collections;
|
|
|
|
namespace winrt::Microsoft::Terminal::Settings::Editor::implementation
|
|
{
|
|
// For ComboBox an empty SelectedItem string denotes no selection.
|
|
// What we want instead is for "Use system language" to be selected by default.
|
|
// --> "und" is synonymous for "Use system language".
|
|
constexpr std::wstring_view systemLanguageTag{ L"und" };
|
|
|
|
GlobalAppearance::GlobalAppearance()
|
|
{
|
|
InitializeComponent();
|
|
|
|
INITIALIZE_BINDABLE_ENUM_SETTING(Theme, ElementTheme, winrt::Windows::UI::Xaml::ElementTheme, L"Globals_Theme", L"Content");
|
|
INITIALIZE_BINDABLE_ENUM_SETTING(TabWidthMode, TabViewWidthMode, winrt::Microsoft::UI::Xaml::Controls::TabViewWidthMode, L"Globals_TabWidthMode", L"Content");
|
|
}
|
|
|
|
void GlobalAppearance::OnNavigatedTo(const NavigationEventArgs& e)
|
|
{
|
|
_State = e.Parameter().as<Editor::GlobalAppearancePageNavigationState>();
|
|
}
|
|
|
|
winrt::hstring GlobalAppearance::LanguageDisplayConverter(const winrt::hstring& tag)
|
|
{
|
|
if (tag == systemLanguageTag)
|
|
{
|
|
return RS_(L"Globals_LanguageDefault");
|
|
}
|
|
|
|
winrt::Windows::Globalization::Language language{ tag };
|
|
return language.NativeName();
|
|
}
|
|
|
|
// Returns the list of languages the user may override the application language with.
|
|
// The returned list are BCP 47 language tags like {"und", "en-US", "de-DE", "es-ES", ...}.
|
|
// "und" is short for "undefined" and is synonymous for "Use system language" in this code.
|
|
winrt::Windows::Foundation::Collections::IObservableVector<winrt::hstring> GlobalAppearance::LanguageList()
|
|
{
|
|
if (_languageList)
|
|
{
|
|
return _languageList;
|
|
}
|
|
|
|
// In order to return the language list this code does the following:
|
|
// [1] Get all possible languages we want to allow the user to choose.
|
|
// We have to acquire languages from multiple sources, creating duplicates. See below at [1].
|
|
// [2] Sort languages by their ASCII tags, forcing the UI in a consistent/stable order.
|
|
// I wanted to sort the localized language names initially, but it turned out to be complex.
|
|
// [3] Remove potential duplicates in our language list from [1].
|
|
// We don't want to have en-US twice in the list, do we?
|
|
// [4] Optionally remove unwanted language tags (like pseudo-localizations).
|
|
|
|
std::vector<winrt::hstring> tags;
|
|
|
|
// [1]:
|
|
{
|
|
// ManifestLanguages contains languages the app ships with.
|
|
//
|
|
// Languages is a computed list that merges the ManifestLanguages with the
|
|
// user's ranked list of preferred languages taken from the system settings.
|
|
// As is tradition the API documentation is incomplete though, as it can also
|
|
// contain regional language variants. If our app supports en-US, but the user
|
|
// has en-GB or en-DE in their system's preferred language list, Languages will
|
|
// contain those as well, as they're variants from a supported language. We should
|
|
// allow a user to select those, as regional formattings can vary significantly.
|
|
const std::array tagSources{
|
|
winrt::Windows::Globalization::ApplicationLanguages::ManifestLanguages(),
|
|
winrt::Windows::Globalization::ApplicationLanguages::Languages()
|
|
};
|
|
|
|
// tags will hold all the flattened results from tagSources.
|
|
// We resize() the vector to the proper size in order to efficiently GetMany() all items.
|
|
tags.resize(std::accumulate(
|
|
tagSources.begin(),
|
|
tagSources.end(),
|
|
// tags[0] will be "und" - the "Use system language" item
|
|
// tags[1..n] will contain tags from tagSources.
|
|
// --> totalTags is offset by 1
|
|
1,
|
|
[](uint32_t sum, const auto& v) -> uint32_t {
|
|
return sum + v.Size();
|
|
}));
|
|
|
|
// As per the function definition, the first item
|
|
// is always "Use system language" ("und").
|
|
auto data = tags.data();
|
|
*data++ = systemLanguageTag;
|
|
|
|
// Finally GetMany() all the tags from tagSources.
|
|
for (const auto& v : tagSources)
|
|
{
|
|
const auto size = v.Size();
|
|
v.GetMany(0, winrt::array_view(data, size));
|
|
data += size;
|
|
}
|
|
}
|
|
|
|
// NOTE: The size of tags is always >0, due to tags[0] being hardcoded to "und".
|
|
const auto tagsBegin = ++tags.begin();
|
|
const auto tagsEnd = tags.end();
|
|
|
|
// [2]:
|
|
std::sort(tagsBegin, tagsEnd);
|
|
|
|
// I'd love for both, std::unique and std::remove_if, to occur in a single loop,
|
|
// but the code turned out to be complex and even less maintainable, so I gave up.
|
|
{
|
|
// [3] part 1:
|
|
auto it = std::unique(tagsBegin, tagsEnd);
|
|
|
|
// The qps- languages are useful for testing ("pseudo-localization").
|
|
// --> Leave them in if debug features are enabled.
|
|
if (!_State.Globals().DebugFeaturesEnabled())
|
|
{
|
|
// [4] part 1:
|
|
it = std::remove_if(tagsBegin, it, [](const winrt::hstring& tag) -> bool {
|
|
return til::starts_with(tag, L"qps-");
|
|
});
|
|
}
|
|
|
|
// [3], [4] part 2 (completing the so called "erase-remove idiom"):
|
|
tags.erase(it, tagsEnd);
|
|
}
|
|
|
|
_languageList = winrt::single_threaded_observable_vector(std::move(tags));
|
|
return _languageList;
|
|
}
|
|
|
|
winrt::Windows::Foundation::IInspectable GlobalAppearance::CurrentLanguage()
|
|
{
|
|
if (_currentLanguage.empty())
|
|
{
|
|
_currentLanguage = winrt::Windows::Globalization::ApplicationLanguages::PrimaryLanguageOverride();
|
|
if (_currentLanguage.empty())
|
|
{
|
|
_currentLanguage = systemLanguageTag;
|
|
}
|
|
}
|
|
|
|
return winrt::box_value(_currentLanguage);
|
|
}
|
|
|
|
void GlobalAppearance::CurrentLanguage(const winrt::Windows::Foundation::IInspectable& tag)
|
|
{
|
|
_currentLanguage = winrt::unbox_value<winrt::hstring>(tag);
|
|
|
|
const auto globals = _State.Globals();
|
|
if (_currentLanguage == systemLanguageTag)
|
|
{
|
|
globals.ClearLanguage();
|
|
}
|
|
else
|
|
{
|
|
globals.Language(_currentLanguage);
|
|
}
|
|
}
|
|
}
|