mirror of
https://github.com/microsoft/terminal.git
synced 2026-02-03 18:17:40 -06:00
Merge branch 'main' into dev/cazamor/sui/search
This commit is contained in:
commit
b540827359
@ -28,7 +28,7 @@ extends:
|
||||
official: true
|
||||
branding: Canary
|
||||
buildTerminal: true
|
||||
pgoBuildMode: None # BODGY - OneBranch is on VS 17.10, which is known to be the worst
|
||||
pgoBuildMode: Optimize
|
||||
codeSign: true
|
||||
signingIdentity:
|
||||
serviceName: $(SigningServiceName)
|
||||
|
||||
@ -34,7 +34,7 @@ struct
|
||||
#else // DEV
|
||||
__declspec(uuid("52065414-e077-47ec-a3ac-1cc5455e1b54"))
|
||||
#endif
|
||||
OpenTerminalHere : public RuntimeClass<RuntimeClassFlags<ClassicCom | InhibitFtmBase>, IExplorerCommand, IObjectWithSite>
|
||||
OpenTerminalHere : public RuntimeClass<RuntimeClassFlags<ClassicCom | InhibitFtmBase>, IExplorerCommand, IObjectWithSite>
|
||||
{
|
||||
#pragma region IExplorerCommand
|
||||
STDMETHODIMP Invoke(IShellItemArray* psiItemArray,
|
||||
|
||||
@ -13,7 +13,7 @@ namespace winrt::Microsoft::TerminalApp::implementation
|
||||
{
|
||||
public:
|
||||
explicit DebugTapConnection(Microsoft::Terminal::TerminalConnection::ITerminalConnection wrappedConnection);
|
||||
void Initialize(const Windows::Foundation::Collections::ValueSet& /*settings*/){};
|
||||
void Initialize(const Windows::Foundation::Collections::ValueSet& /*settings*/) {};
|
||||
~DebugTapConnection();
|
||||
void Start();
|
||||
void WriteInput(const winrt::array_view<const char16_t> data);
|
||||
|
||||
@ -25,7 +25,7 @@ namespace winrt::TerminalApp::implementation
|
||||
#pragma region IPaneContent
|
||||
winrt::Windows::UI::Xaml::FrameworkElement GetRoot();
|
||||
|
||||
void UpdateSettings(const winrt::Microsoft::Terminal::Settings::Model::CascadiaSettings&){};
|
||||
void UpdateSettings(const winrt::Microsoft::Terminal::Settings::Model::CascadiaSettings&) {};
|
||||
|
||||
winrt::Windows::Foundation::Size MinimumSize() { return { 1, 1 }; };
|
||||
void Focus(winrt::Windows::UI::Xaml::FocusState reason = winrt::Windows::UI::Xaml::FocusState::Programmatic) { reason; };
|
||||
|
||||
@ -9,7 +9,7 @@ namespace winrt::TerminalApp::implementation
|
||||
{
|
||||
// Default to unset, 0%.
|
||||
TaskbarState::TaskbarState() :
|
||||
TaskbarState(0, 0){};
|
||||
TaskbarState(0, 0) {};
|
||||
|
||||
TaskbarState::TaskbarState(const uint64_t dispatchTypesState, const uint64_t progressParam) :
|
||||
_State{ dispatchTypesState },
|
||||
|
||||
@ -31,7 +31,7 @@ Author(s):
|
||||
using NewHandoffFunction = HRESULT (*)(HANDLE* in, HANDLE* out, HANDLE signal, HANDLE reference, HANDLE server, HANDLE client, const TERMINAL_STARTUP_INFO* startupInfo);
|
||||
|
||||
struct __declspec(uuid(__CLSID_CTerminalHandoff))
|
||||
CTerminalHandoff : public Microsoft::WRL::RuntimeClass<Microsoft::WRL::RuntimeClassFlags<Microsoft::WRL::RuntimeClassType::ClassicCom>, ITerminalHandoff3>
|
||||
CTerminalHandoff : public Microsoft::WRL::RuntimeClass<Microsoft::WRL::RuntimeClassFlags<Microsoft::WRL::RuntimeClassType::ClassicCom>, ITerminalHandoff3>
|
||||
{
|
||||
#pragma region ITerminalHandoff
|
||||
STDMETHODIMP EstablishPtyHandoff(HANDLE* in, HANDLE* out, HANDLE signal, HANDLE reference, HANDLE server, HANDLE client, const TERMINAL_STARTUP_INFO* startupInfo) override;
|
||||
|
||||
@ -958,7 +958,7 @@ void _stdcall TerminalSetTheme(void* terminal, TerminalTheme theme, LPCWSTR font
|
||||
for (size_t tableIndex = 0; tableIndex < 16; tableIndex++)
|
||||
{
|
||||
// It's using gsl::at to check the index is in bounds, but the analyzer still calls this array-to-pointer-decay
|
||||
GSL_SUPPRESS(bounds .3)
|
||||
GSL_SUPPRESS(bounds.3)
|
||||
renderSettings.SetColorTableEntry(tableIndex, gsl::at(theme.ColorTable, tableIndex));
|
||||
}
|
||||
|
||||
|
||||
@ -502,7 +502,13 @@ namespace winrt::Microsoft::Terminal::Settings::Editor::implementation
|
||||
auto lifetime = get_strong();
|
||||
|
||||
static constexpr winrt::guid clientGuidFiles{ 0xbd00ae34, 0x839b, 0x43f6, { 0x8b, 0x94, 0x12, 0x37, 0x1a, 0xfe, 0xea, 0xb5 } };
|
||||
const auto parentHwnd{ reinterpret_cast<HWND>(_WindowRoot.GetHostingWindow()) };
|
||||
|
||||
const auto windowRoot = WindowRoot();
|
||||
if (!windowRoot)
|
||||
{
|
||||
co_return;
|
||||
}
|
||||
const auto parentHwnd{ reinterpret_cast<HWND>(windowRoot.GetHostingWindow()) };
|
||||
auto path = co_await OpenFilePicker(parentHwnd, [](auto&& dialog) {
|
||||
THROW_IF_FAILED(dialog->SetClientGuid(clientGuidFiles));
|
||||
try
|
||||
@ -525,8 +531,13 @@ namespace winrt::Microsoft::Terminal::Settings::Editor::implementation
|
||||
auto lifetime = get_strong();
|
||||
|
||||
static constexpr winrt::guid clientGuidFolders{ 0xa611027, 0x42be, 0x4665, { 0xaf, 0xf1, 0x3f, 0x22, 0x26, 0xe9, 0xf7, 0x4d } };
|
||||
;
|
||||
const auto parentHwnd{ reinterpret_cast<HWND>(_WindowRoot.GetHostingWindow()) };
|
||||
|
||||
const auto windowRoot = WindowRoot();
|
||||
if (!windowRoot)
|
||||
{
|
||||
co_return;
|
||||
}
|
||||
const auto parentHwnd{ reinterpret_cast<HWND>(windowRoot.GetHostingWindow()) };
|
||||
auto path = co_await OpenFilePicker(parentHwnd, [](auto&& dialog) {
|
||||
THROW_IF_FAILED(dialog->SetClientGuid(clientGuidFolders));
|
||||
try
|
||||
|
||||
@ -141,6 +141,8 @@ namespace winrt::Microsoft::Terminal::Settings::Editor::implementation
|
||||
winrt::hstring Type() const noexcept { return _descriptor.Type; };
|
||||
Model::ArgTypeHint TypeHint() const noexcept { return _descriptor.TypeHint; };
|
||||
bool Required() const noexcept { return _descriptor.Required; };
|
||||
Editor::IHostedInWindow WindowRoot() const noexcept { return _WeakWindowRoot.get(); }
|
||||
void WindowRoot(const Editor::IHostedInWindow& value) { _WeakWindowRoot = value; }
|
||||
|
||||
// We cannot use the macro here because we need to implement additional logic for the setter
|
||||
Windows::Foundation::IInspectable EnumValue() const noexcept { return _EnumValue; };
|
||||
@ -186,10 +188,10 @@ namespace winrt::Microsoft::Terminal::Settings::Editor::implementation
|
||||
VIEW_MODEL_OBSERVABLE_PROPERTY(Editor::ColorSchemeViewModel, DefaultColorScheme, nullptr);
|
||||
VIEW_MODEL_OBSERVABLE_PROPERTY(Windows::Foundation::IInspectable, Value, nullptr);
|
||||
WINRT_PROPERTY(Windows::Foundation::Collections::IVector<winrt::hstring>, ColorSchemeNamesList, nullptr);
|
||||
WINRT_PROPERTY(Editor::IHostedInWindow, WindowRoot, nullptr);
|
||||
|
||||
private:
|
||||
Model::ArgDescriptor _descriptor;
|
||||
winrt::weak_ref<Editor::IHostedInWindow> _WeakWindowRoot{ nullptr };
|
||||
Windows::Foundation::IInspectable _EnumValue{ nullptr };
|
||||
Windows::Foundation::Collections::IObservableVector<Microsoft::Terminal::Settings::Editor::EnumEntry> _EnumList;
|
||||
Windows::Foundation::Collections::IObservableVector<Microsoft::Terminal::Settings::Editor::FlagEntry> _FlagList;
|
||||
|
||||
@ -1444,10 +1444,15 @@ namespace winrt::Microsoft::Terminal::Settings::Editor::implementation
|
||||
|
||||
safe_void_coroutine Appearances::BackgroundImage_Click(const IInspectable&, const RoutedEventArgs&)
|
||||
{
|
||||
auto lifetime = get_strong();
|
||||
const auto lifetime = get_strong();
|
||||
|
||||
const auto parentHwnd{ reinterpret_cast<HWND>(WindowRoot().GetHostingWindow()) };
|
||||
auto file = co_await OpenImagePicker(parentHwnd);
|
||||
const auto windowRoot = WindowRoot();
|
||||
if (!windowRoot)
|
||||
{
|
||||
co_return;
|
||||
}
|
||||
const auto parentHwnd{ reinterpret_cast<HWND>(windowRoot.GetHostingWindow()) };
|
||||
const auto file = co_await OpenImagePicker(parentHwnd);
|
||||
if (!file.empty())
|
||||
{
|
||||
Appearance().SetBackgroundImagePath(file);
|
||||
|
||||
@ -193,6 +193,9 @@ namespace winrt::Microsoft::Terminal::Settings::Editor::implementation
|
||||
// CursorShape visibility logic
|
||||
bool IsVintageCursor() const;
|
||||
|
||||
Editor::IHostedInWindow WindowRoot() const noexcept { return _WeakWindowRoot.get(); }
|
||||
void WindowRoot(const Editor::IHostedInWindow& value) noexcept { _WeakWindowRoot = value; }
|
||||
|
||||
Windows::Foundation::Collections::IObservableVector<Editor::Font> FilteredFontList();
|
||||
bool ShowAllFonts() const noexcept;
|
||||
void ShowAllFonts(bool value);
|
||||
@ -220,12 +223,12 @@ namespace winrt::Microsoft::Terminal::Settings::Editor::implementation
|
||||
|
||||
DEPENDENCY_PROPERTY(Editor::AppearanceViewModel, Appearance);
|
||||
WINRT_PROPERTY(Editor::ProfileViewModel, SourceProfile, nullptr);
|
||||
WINRT_PROPERTY(IHostedInWindow, WindowRoot, nullptr);
|
||||
GETSET_BINDABLE_ENUM_SETTING(BackgroundImageStretchMode, Windows::UI::Xaml::Media::Stretch, Appearance().BackgroundImageStretchMode);
|
||||
|
||||
GETSET_BINDABLE_ENUM_SETTING(IntenseTextStyle, Microsoft::Terminal::Settings::Model::IntenseStyle, Appearance().IntenseTextStyle);
|
||||
|
||||
private:
|
||||
winrt::weak_ref<Editor::IHostedInWindow> _WeakWindowRoot{ nullptr };
|
||||
Windows::UI::Xaml::Data::INotifyPropertyChanged::PropertyChanged_revoker _ViewModelChangedRevoker;
|
||||
std::array<Windows::UI::Xaml::Controls::Primitives::ToggleButton, 9> _BIAlignmentButtons;
|
||||
Windows::Foundation::Collections::IMap<uint16_t, Microsoft::Terminal::Settings::Editor::EnumEntry> _FontWeightMap;
|
||||
|
||||
320
src/cascadia/TerminalSettingsEditor/IconPicker.cpp
Normal file
320
src/cascadia/TerminalSettingsEditor/IconPicker.cpp
Normal file
@ -0,0 +1,320 @@
|
||||
// Copyright (c) Microsoft Corporation.
|
||||
// Licensed under the MIT license.
|
||||
|
||||
#include "pch.h"
|
||||
#include "IconPicker.h"
|
||||
#include "IconPicker.g.cpp"
|
||||
|
||||
#include <LibraryResources.h>
|
||||
#include "SegoeFluentIconList.h"
|
||||
#include "../../types/inc/utils.hpp"
|
||||
#include "../WinRTUtils/inc/Utils.h"
|
||||
|
||||
using namespace winrt;
|
||||
using namespace winrt::Windows::UI;
|
||||
using namespace winrt::Windows::UI::Xaml;
|
||||
using namespace winrt::Windows::UI::Xaml::Navigation;
|
||||
using namespace winrt::Windows::UI::Xaml::Controls;
|
||||
using namespace winrt::Windows::UI::Xaml::Media;
|
||||
using namespace winrt::Windows::Foundation;
|
||||
using namespace winrt::Windows::Foundation::Collections;
|
||||
using namespace winrt::Microsoft::UI::Xaml::Controls;
|
||||
|
||||
namespace winrt
|
||||
{
|
||||
namespace MUX = Microsoft::UI::Xaml;
|
||||
namespace WUX = Windows::UI::Xaml;
|
||||
}
|
||||
|
||||
namespace winrt::Microsoft::Terminal::Settings::Editor::implementation
|
||||
{
|
||||
static constexpr std::wstring_view HideIconValue{ L"none" };
|
||||
|
||||
Windows::Foundation::Collections::IObservableVector<Editor::EnumEntry> IconPicker::_BuiltInIcons{ nullptr };
|
||||
Windows::Foundation::Collections::IObservableVector<Editor::EnumEntry> IconPicker::_IconTypes{ nullptr };
|
||||
DependencyProperty IconPicker::_CurrentIconPathProperty{ nullptr };
|
||||
|
||||
Windows::Foundation::Collections::IObservableVector<Editor::EnumEntry> IconPicker::BuiltInIcons() noexcept
|
||||
{
|
||||
if (!_BuiltInIcons)
|
||||
{
|
||||
// lazy load the built-in icons
|
||||
std::vector<Editor::EnumEntry> builtInIcons;
|
||||
for (auto& [val, name] : s_SegoeFluentIcons)
|
||||
{
|
||||
builtInIcons.emplace_back(make<EnumEntry>(hstring{ name }, box_value(val)));
|
||||
}
|
||||
_BuiltInIcons = single_threaded_observable_vector<Editor::EnumEntry>(std::move(builtInIcons));
|
||||
}
|
||||
return _BuiltInIcons;
|
||||
}
|
||||
|
||||
Windows::Foundation::Collections::IObservableVector<Editor::EnumEntry> IconPicker::IconTypes() noexcept
|
||||
{
|
||||
if (!_IconTypes)
|
||||
{
|
||||
// lazy load the icon types
|
||||
std::vector<Editor::EnumEntry> iconTypes;
|
||||
iconTypes.reserve(4);
|
||||
iconTypes.emplace_back(make<EnumEntry>(RS_(L"IconPicker_IconTypeNone"), box_value(IconType::None)));
|
||||
iconTypes.emplace_back(make<EnumEntry>(RS_(L"IconPicker_IconTypeFontIcon"), box_value(IconType::FontIcon)));
|
||||
iconTypes.emplace_back(make<EnumEntry>(RS_(L"IconPicker_IconTypeEmoji"), box_value(IconType::Emoji)));
|
||||
iconTypes.emplace_back(make<EnumEntry>(RS_(L"IconPicker_IconTypeImage"), box_value(IconType::Image)));
|
||||
_IconTypes = winrt::single_threaded_observable_vector<Editor::EnumEntry>(std::move(iconTypes));
|
||||
}
|
||||
return _IconTypes;
|
||||
}
|
||||
|
||||
IconPicker::IconPicker()
|
||||
{
|
||||
_InitializeProperties();
|
||||
InitializeComponent();
|
||||
|
||||
_DeduceCurrentIconType();
|
||||
PropertyChanged([this](auto&&, const PropertyChangedEventArgs& args) {
|
||||
const auto propertyName{ args.PropertyName() };
|
||||
// "CurrentIconPath" changes are handled by _OnCurrentIconPathChanged()
|
||||
if (propertyName == L"CurrentIconType")
|
||||
{
|
||||
PropertyChanged.raise(*this, Windows::UI::Xaml::Data::PropertyChangedEventArgs{ L"UsingNoIcon" });
|
||||
PropertyChanged.raise(*this, Windows::UI::Xaml::Data::PropertyChangedEventArgs{ L"UsingBuiltInIcon" });
|
||||
PropertyChanged.raise(*this, Windows::UI::Xaml::Data::PropertyChangedEventArgs{ L"UsingEmojiIcon" });
|
||||
PropertyChanged.raise(*this, Windows::UI::Xaml::Data::PropertyChangedEventArgs{ L"UsingImageIcon" });
|
||||
}
|
||||
else if (propertyName == L"CurrentBuiltInIcon")
|
||||
{
|
||||
CurrentIconPath(unbox_value<hstring>(_CurrentBuiltInIcon.EnumValue()));
|
||||
}
|
||||
else if (propertyName == L"CurrentEmojiIcon")
|
||||
{
|
||||
CurrentIconPath(CurrentEmojiIcon());
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
void IconPicker::_InitializeProperties()
|
||||
{
|
||||
// Initialize any dependency properties here.
|
||||
// This performs a lazy load on these properties, instead of
|
||||
// initializing them when the DLL loads.
|
||||
if (!_CurrentIconPathProperty)
|
||||
{
|
||||
_CurrentIconPathProperty =
|
||||
DependencyProperty::Register(
|
||||
L"CurrentIconPath",
|
||||
xaml_typename<hstring>(),
|
||||
xaml_typename<Editor::IconPicker>(),
|
||||
PropertyMetadata{ nullptr, PropertyChangedCallback{ &IconPicker::_OnCurrentIconPathChanged } });
|
||||
}
|
||||
}
|
||||
|
||||
void IconPicker::_OnCurrentIconPathChanged(const DependencyObject& d, const DependencyPropertyChangedEventArgs& /*e*/)
|
||||
{
|
||||
d.as<IconPicker>()->_DeduceCurrentIconType();
|
||||
}
|
||||
|
||||
safe_void_coroutine IconPicker::Icon_Click(const IInspectable&, const RoutedEventArgs&)
|
||||
{
|
||||
auto lifetime = get_strong();
|
||||
|
||||
const auto parentHwnd{ reinterpret_cast<HWND>(WindowRoot().GetHostingWindow()) };
|
||||
auto file = co_await OpenImagePicker(parentHwnd);
|
||||
if (!file.empty())
|
||||
{
|
||||
CurrentIconPath(file);
|
||||
}
|
||||
}
|
||||
|
||||
void IconPicker::BuiltInIconPicker_GotFocus(const IInspectable& sender, const RoutedEventArgs& /*e*/)
|
||||
{
|
||||
_updateIconFilter({});
|
||||
sender.as<AutoSuggestBox>().IsSuggestionListOpen(true);
|
||||
}
|
||||
|
||||
void IconPicker::BuiltInIconPicker_QuerySubmitted(const AutoSuggestBox& /*sender*/, const AutoSuggestBoxQuerySubmittedEventArgs& e)
|
||||
{
|
||||
const auto iconEntry = unbox_value_or<Editor::EnumEntry>(e.ChosenSuggestion(), nullptr);
|
||||
if (!iconEntry)
|
||||
{
|
||||
return;
|
||||
}
|
||||
CurrentBuiltInIcon(iconEntry);
|
||||
}
|
||||
|
||||
void IconPicker::BuiltInIconPicker_TextChanged(const AutoSuggestBox& sender, const AutoSuggestBoxTextChangedEventArgs& e)
|
||||
{
|
||||
if (e.Reason() != AutoSuggestionBoxTextChangeReason::UserInput)
|
||||
{
|
||||
return;
|
||||
}
|
||||
std::wstring_view filter{ sender.Text() };
|
||||
filter = til::trim(filter, L' ');
|
||||
_updateIconFilter(filter);
|
||||
}
|
||||
|
||||
void IconPicker::_updateIconFilter(std::wstring_view filter)
|
||||
{
|
||||
if (_iconFilter != filter)
|
||||
{
|
||||
_filteredBuiltInIcons = nullptr;
|
||||
_iconFilter = filter;
|
||||
_updateFilteredIconList();
|
||||
PropertyChanged.raise(*this, PropertyChangedEventArgs{ L"FilteredBuiltInIconList" });
|
||||
}
|
||||
}
|
||||
|
||||
Windows::Foundation::Collections::IObservableVector<Editor::EnumEntry> IconPicker::FilteredBuiltInIconList()
|
||||
{
|
||||
if (!_filteredBuiltInIcons)
|
||||
{
|
||||
_updateFilteredIconList();
|
||||
}
|
||||
return _filteredBuiltInIcons;
|
||||
}
|
||||
|
||||
void IconPicker::_updateFilteredIconList()
|
||||
{
|
||||
_filteredBuiltInIcons = BuiltInIcons();
|
||||
if (_iconFilter.empty())
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
// Find matching icons and populate the filtered list
|
||||
std::vector<Editor::EnumEntry> filtered;
|
||||
filtered.reserve(_filteredBuiltInIcons.Size());
|
||||
for (const auto& icon : _filteredBuiltInIcons)
|
||||
{
|
||||
if (til::contains_linguistic_insensitive(icon.EnumName(), _iconFilter))
|
||||
{
|
||||
filtered.emplace_back(icon);
|
||||
}
|
||||
}
|
||||
_filteredBuiltInIcons = winrt::single_threaded_observable_vector(std::move(filtered));
|
||||
}
|
||||
|
||||
void IconPicker::CurrentIconType(const Windows::Foundation::IInspectable& value)
|
||||
{
|
||||
if (_currentIconType != value)
|
||||
{
|
||||
// Switching from...
|
||||
if (_currentIconType && unbox_value<IconType>(_currentIconType.as<Editor::EnumEntry>().EnumValue()) == IconType::Image)
|
||||
{
|
||||
// Stash the current value of Icon. If the user
|
||||
// switches out of then back to IconType::Image, we want
|
||||
// the path that we display in the text box to remain unchanged.
|
||||
_lastIconPath = CurrentIconPath();
|
||||
}
|
||||
|
||||
// Set the member here instead of after setting Icon() below!
|
||||
// We have an Icon property changed handler defined for when we discard changes.
|
||||
// Inadvertently, that means that we call this setter again.
|
||||
// Setting the member here means that we early exit at the beginning of the function
|
||||
// because _currentIconType == value.
|
||||
_currentIconType = value;
|
||||
|
||||
// Switched to...
|
||||
switch (unbox_value<IconType>(value.as<Editor::EnumEntry>().EnumValue()))
|
||||
{
|
||||
case IconType::None:
|
||||
{
|
||||
CurrentIconPath(winrt::hstring{ HideIconValue });
|
||||
break;
|
||||
}
|
||||
case IconType::Image:
|
||||
{
|
||||
if (!_lastIconPath.empty())
|
||||
{
|
||||
// Conversely, if we switch to Image,
|
||||
// retrieve that saved value and apply it
|
||||
CurrentIconPath(_lastIconPath);
|
||||
}
|
||||
break;
|
||||
}
|
||||
case IconType::FontIcon:
|
||||
{
|
||||
if (_CurrentBuiltInIcon)
|
||||
{
|
||||
CurrentIconPath(unbox_value<hstring>(_CurrentBuiltInIcon.EnumValue()));
|
||||
}
|
||||
break;
|
||||
}
|
||||
case IconType::Emoji:
|
||||
{
|
||||
// Don't set Icon here!
|
||||
// Clear out the text box so we direct the user to use the emoji picker.
|
||||
CurrentEmojiIcon({});
|
||||
}
|
||||
}
|
||||
// We're not using the VM's Icon() setter above,
|
||||
// so notify HasIcon changed manually
|
||||
PropertyChanged.raise(*this, Windows::UI::Xaml::Data::PropertyChangedEventArgs{ L"CurrentIconType" });
|
||||
PropertyChanged.raise(*this, Windows::UI::Xaml::Data::PropertyChangedEventArgs{ L"HasIcon" });
|
||||
}
|
||||
}
|
||||
|
||||
bool IconPicker::UsingNoIcon() const
|
||||
{
|
||||
return _currentIconType == IconTypes().GetAt(0);
|
||||
}
|
||||
|
||||
bool IconPicker::UsingBuiltInIcon() const
|
||||
{
|
||||
return _currentIconType == IconTypes().GetAt(1);
|
||||
}
|
||||
|
||||
bool IconPicker::UsingEmojiIcon() const
|
||||
{
|
||||
return _currentIconType == IconTypes().GetAt(2);
|
||||
}
|
||||
|
||||
bool IconPicker::UsingImageIcon() const
|
||||
{
|
||||
return _currentIconType == IconTypes().GetAt(3);
|
||||
}
|
||||
|
||||
void IconPicker::_DeduceCurrentIconType()
|
||||
{
|
||||
const auto icon = CurrentIconPath();
|
||||
if (icon.empty() || icon == HideIconValue)
|
||||
{
|
||||
_currentIconType = IconTypes().GetAt(0);
|
||||
}
|
||||
else if (icon.size() == 1 && (L'\uE700' <= til::at(icon, 0) && til::at(icon, 0) <= L'\uF8B3'))
|
||||
{
|
||||
_currentIconType = IconTypes().GetAt(1);
|
||||
_DeduceCurrentBuiltInIcon();
|
||||
}
|
||||
else if (::Microsoft::Console::Utils::IsLikelyToBeEmojiOrSymbolIcon(icon))
|
||||
{
|
||||
// We already did a range check for MDL2 Assets in the previous one,
|
||||
// so if we're out of that range but still short, assume we're an emoji
|
||||
_currentIconType = IconTypes().GetAt(2);
|
||||
}
|
||||
else
|
||||
{
|
||||
_currentIconType = IconTypes().GetAt(3);
|
||||
}
|
||||
PropertyChanged.raise(*this, Windows::UI::Xaml::Data::PropertyChangedEventArgs{ L"CurrentIconType" });
|
||||
}
|
||||
|
||||
void IconPicker::_DeduceCurrentBuiltInIcon()
|
||||
{
|
||||
const auto icon = CurrentIconPath();
|
||||
for (uint32_t i = 0; i < BuiltInIcons().Size(); i++)
|
||||
{
|
||||
const auto& builtIn = BuiltInIcons().GetAt(i);
|
||||
if (icon == unbox_value<hstring>(builtIn.EnumValue()))
|
||||
{
|
||||
CurrentBuiltInIcon(builtIn);
|
||||
return;
|
||||
}
|
||||
}
|
||||
CurrentBuiltInIcon(BuiltInIcons().GetAt(0));
|
||||
}
|
||||
|
||||
WUX::Controls::IconSource IconPicker::BuiltInIconConverter(const IInspectable& iconVal)
|
||||
{
|
||||
return Microsoft::Terminal::UI::IconPathConverter::IconSourceWUX(unbox_value<hstring>(iconVal));
|
||||
}
|
||||
}
|
||||
68
src/cascadia/TerminalSettingsEditor/IconPicker.h
Normal file
68
src/cascadia/TerminalSettingsEditor/IconPicker.h
Normal file
@ -0,0 +1,68 @@
|
||||
// Copyright (c) Microsoft Corporation.
|
||||
// Licensed under the MIT license.
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "IconPicker.g.h"
|
||||
#include "EnumEntry.h"
|
||||
#include "Utils.h"
|
||||
#include "cppwinrt_utils.h"
|
||||
|
||||
namespace winrt::Microsoft::Terminal::Settings::Editor::implementation
|
||||
{
|
||||
struct IconPicker : public HasScrollViewer<IconPicker>, IconPickerT<IconPicker>
|
||||
{
|
||||
public:
|
||||
IconPicker();
|
||||
|
||||
static constexpr std::wstring_view HideIconValue{ L"none" };
|
||||
static Windows::UI::Xaml::Controls::IconSource BuiltInIconConverter(const Windows::Foundation::IInspectable& iconVal);
|
||||
static Windows::Foundation::Collections::IObservableVector<Editor::EnumEntry> BuiltInIcons() noexcept;
|
||||
static Windows::Foundation::Collections::IObservableVector<Editor::EnumEntry> IconTypes() noexcept;
|
||||
|
||||
Windows::Foundation::Collections::IObservableVector<Editor::EnumEntry> FilteredBuiltInIconList();
|
||||
safe_void_coroutine Icon_Click(const Windows::Foundation::IInspectable& sender, const Windows::UI::Xaml::RoutedEventArgs& e);
|
||||
void BuiltInIconPicker_GotFocus(const Windows::Foundation::IInspectable& sender, const Windows::UI::Xaml::RoutedEventArgs& e);
|
||||
void BuiltInIconPicker_TextChanged(const winrt::Windows::UI::Xaml::Controls::AutoSuggestBox& sender, const Windows::UI::Xaml::Controls::AutoSuggestBoxTextChangedEventArgs& e);
|
||||
void BuiltInIconPicker_QuerySubmitted(const winrt::Windows::UI::Xaml::Controls::AutoSuggestBox& sender, const Windows::UI::Xaml::Controls::AutoSuggestBoxQuerySubmittedEventArgs& e);
|
||||
|
||||
Windows::Foundation::IInspectable CurrentIconType() const noexcept { return _currentIconType; }
|
||||
void CurrentIconType(const Windows::Foundation::IInspectable& value);
|
||||
|
||||
Editor::IHostedInWindow WindowRoot() const noexcept { return _weakWindowRoot.get(); }
|
||||
void WindowRoot(const Editor::IHostedInWindow& value) noexcept { _weakWindowRoot = value; }
|
||||
|
||||
bool UsingNoIcon() const;
|
||||
bool UsingBuiltInIcon() const;
|
||||
bool UsingEmojiIcon() const;
|
||||
bool UsingImageIcon() const;
|
||||
|
||||
til::property_changed_event PropertyChanged;
|
||||
WINRT_OBSERVABLE_PROPERTY(hstring, CurrentEmojiIcon, PropertyChanged.raise);
|
||||
WINRT_OBSERVABLE_PROPERTY(Editor::EnumEntry, CurrentBuiltInIcon, PropertyChanged.raise, nullptr);
|
||||
|
||||
DEPENDENCY_PROPERTY(hstring, CurrentIconPath);
|
||||
|
||||
private:
|
||||
static Windows::Foundation::Collections::IObservableVector<Editor::EnumEntry> _BuiltInIcons;
|
||||
static Windows::Foundation::Collections::IObservableVector<Editor::EnumEntry> _IconTypes;
|
||||
Windows::Foundation::Collections::IObservableVector<Editor::EnumEntry> _filteredBuiltInIcons;
|
||||
std::wstring _iconFilter;
|
||||
Windows::Foundation::IInspectable _currentIconType{};
|
||||
winrt::hstring _lastIconPath;
|
||||
winrt::weak_ref<Editor::IHostedInWindow> _weakWindowRoot;
|
||||
|
||||
static void _InitializeProperties();
|
||||
static void _OnCurrentIconPathChanged(const Windows::UI::Xaml::DependencyObject& d, const Windows::UI::Xaml::DependencyPropertyChangedEventArgs& e);
|
||||
|
||||
void _DeduceCurrentIconType();
|
||||
void _DeduceCurrentBuiltInIcon();
|
||||
void _updateIconFilter(std::wstring_view filter);
|
||||
void _updateFilteredIconList();
|
||||
};
|
||||
}
|
||||
|
||||
namespace winrt::Microsoft::Terminal::Settings::Editor::factory_implementation
|
||||
{
|
||||
BASIC_FACTORY(IconPicker);
|
||||
}
|
||||
41
src/cascadia/TerminalSettingsEditor/IconPicker.idl
Normal file
41
src/cascadia/TerminalSettingsEditor/IconPicker.idl
Normal file
@ -0,0 +1,41 @@
|
||||
// Copyright (c) Microsoft Corporation.
|
||||
// Licensed under the MIT license.
|
||||
|
||||
import "EnumEntry.idl";
|
||||
import "MainPage.idl";
|
||||
|
||||
namespace Microsoft.Terminal.Settings.Editor
|
||||
{
|
||||
enum IconType
|
||||
{
|
||||
None = 0,
|
||||
FontIcon,
|
||||
Image,
|
||||
Emoji
|
||||
};
|
||||
|
||||
[default_interface] runtimeclass IconPicker : Windows.UI.Xaml.Controls.UserControl, Windows.UI.Xaml.Data.INotifyPropertyChanged
|
||||
{
|
||||
IconPicker();
|
||||
|
||||
IInspectable CurrentIconType;
|
||||
Windows.Foundation.Collections.IObservableVector<EnumEntry> IconTypes { get; };
|
||||
|
||||
Boolean UsingBuiltInIcon { get; };
|
||||
Boolean UsingEmojiIcon { get; };
|
||||
Boolean UsingImageIcon { get; };
|
||||
|
||||
String CurrentEmojiIcon;
|
||||
|
||||
EnumEntry CurrentBuiltInIcon;
|
||||
Windows.Foundation.Collections.IObservableVector<EnumEntry> BuiltInIcons { get; };
|
||||
Windows.Foundation.Collections.IObservableVector<EnumEntry> FilteredBuiltInIconList { get; };
|
||||
|
||||
static Windows.UI.Xaml.Controls.IconSource BuiltInIconConverter(IInspectable iconVal);
|
||||
|
||||
String CurrentIconPath;
|
||||
static Windows.UI.Xaml.DependencyProperty CurrentIconPathProperty { get; };
|
||||
|
||||
IHostedInWindow WindowRoot;
|
||||
}
|
||||
}
|
||||
100
src/cascadia/TerminalSettingsEditor/IconPicker.xaml
Normal file
100
src/cascadia/TerminalSettingsEditor/IconPicker.xaml
Normal file
@ -0,0 +1,100 @@
|
||||
<!--
|
||||
Copyright (c) Microsoft Corporation. All rights reserved. Licensed under
|
||||
the MIT License. See LICENSE in the project root for license information.
|
||||
-->
|
||||
<UserControl x:Class="Microsoft.Terminal.Settings.Editor.IconPicker"
|
||||
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
|
||||
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
|
||||
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
|
||||
xmlns:local="using:Microsoft.Terminal.Settings.Editor"
|
||||
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
|
||||
xmlns:model="using:Microsoft.Terminal.Settings.Model"
|
||||
xmlns:mtu="using:Microsoft.Terminal.UI"
|
||||
xmlns:muxc="using:Microsoft.UI.Xaml.Controls"
|
||||
mc:Ignorable="d">
|
||||
|
||||
<UserControl.Resources>
|
||||
<ResourceDictionary>
|
||||
<ResourceDictionary.MergedDictionaries>
|
||||
<ResourceDictionary Source="CommonResources.xaml" />
|
||||
</ResourceDictionary.MergedDictionaries>
|
||||
</ResourceDictionary>
|
||||
</UserControl.Resources>
|
||||
|
||||
<Grid ColumnSpacing="12">
|
||||
<Grid.ColumnDefinitions>
|
||||
<ColumnDefinition Width="auto" />
|
||||
<ColumnDefinition Width="*" />
|
||||
<ColumnDefinition Width="auto" />
|
||||
</Grid.ColumnDefinitions>
|
||||
|
||||
<!-- Icon Type -->
|
||||
<ComboBox x:Uid="IconPicker_IconType"
|
||||
Grid.Column="0"
|
||||
ItemsSource="{x:Bind IconTypes}"
|
||||
SelectedItem="{x:Bind CurrentIconType, Mode=TwoWay}">
|
||||
<ComboBox.ItemTemplate>
|
||||
<DataTemplate x:DataType="local:EnumEntry">
|
||||
<TextBlock Text="{x:Bind EnumName}" />
|
||||
</DataTemplate>
|
||||
</ComboBox.ItemTemplate>
|
||||
</ComboBox>
|
||||
|
||||
<!-- Built-In Icon -->
|
||||
<AutoSuggestBox x:Uid="IconPicker_BuiltInIcon"
|
||||
Grid.Column="1"
|
||||
GotFocus="BuiltInIconPicker_GotFocus"
|
||||
ItemsSource="{x:Bind FilteredBuiltInIconList, Mode=OneWay}"
|
||||
QuerySubmitted="BuiltInIconPicker_QuerySubmitted"
|
||||
Text="{x:Bind CurrentBuiltInIcon.EnumName, Mode=OneWay}"
|
||||
TextBoxStyle="{StaticResource TextBoxSettingStyle}"
|
||||
TextChanged="BuiltInIconPicker_TextChanged"
|
||||
Visibility="{x:Bind UsingBuiltInIcon, Mode=OneWay}">
|
||||
<AutoSuggestBox.ItemTemplate>
|
||||
<DataTemplate x:DataType="local:EnumEntry">
|
||||
<Grid ColumnSpacing="12">
|
||||
<Grid.ColumnDefinitions>
|
||||
<ColumnDefinition Width="16" />
|
||||
<ColumnDefinition Width="*" />
|
||||
</Grid.ColumnDefinitions>
|
||||
|
||||
<IconSourceElement Grid.Column="0"
|
||||
Width="16"
|
||||
Height="16"
|
||||
IconSource="{x:Bind local:IconPicker.BuiltInIconConverter(EnumValue), Mode=OneTime}" />
|
||||
<TextBlock Grid.Column="1"
|
||||
Text="{x:Bind EnumName}" />
|
||||
</Grid>
|
||||
</DataTemplate>
|
||||
</AutoSuggestBox.ItemTemplate>
|
||||
</AutoSuggestBox>
|
||||
|
||||
<!-- Image (File) Icon -->
|
||||
<TextBox x:Uid="IconPicker_ImagePathBox"
|
||||
Grid.Column="1"
|
||||
MaxWidth="Infinity"
|
||||
HorizontalAlignment="Stretch"
|
||||
FontFamily="Segoe UI, Segoe Fluent Icons, Segoe MDL2 Assets"
|
||||
IsSpellCheckEnabled="False"
|
||||
Style="{StaticResource TextBoxSettingStyle}"
|
||||
Text="{x:Bind CurrentIconPath, Mode=TwoWay}"
|
||||
Visibility="{x:Bind UsingImageIcon, Mode=OneWay}" />
|
||||
<Button x:Uid="IconPicker_IconBrowse"
|
||||
Grid.Column="2"
|
||||
Margin="0"
|
||||
VerticalAlignment="Top"
|
||||
Click="Icon_Click"
|
||||
Style="{StaticResource BrowseButtonStyle}"
|
||||
Visibility="{x:Bind UsingImageIcon, Mode=OneWay}" />
|
||||
|
||||
<!-- Emoji Icon -->
|
||||
<TextBox x:Uid="IconPicker_EmojiBox"
|
||||
Grid.Column="1"
|
||||
MaxWidth="Infinity"
|
||||
FontFamily="Segoe UI, Segoe Fluent Icons, Segoe MDL2 Assets"
|
||||
IsSpellCheckEnabled="False"
|
||||
Style="{StaticResource TextBoxSettingStyle}"
|
||||
Text="{x:Bind CurrentEmojiIcon, Mode=TwoWay}"
|
||||
Visibility="{x:Bind UsingEmojiIcon, Mode=OneWay}" />
|
||||
</Grid>
|
||||
</UserControl>
|
||||
@ -69,6 +69,10 @@
|
||||
<DependentUpon>NullableColorPicker.xaml</DependentUpon>
|
||||
<SubType>Code</SubType>
|
||||
</ClInclude>
|
||||
<ClInclude Include="IconPicker.h">
|
||||
<DependentUpon>IconPicker.xaml</DependentUpon>
|
||||
<SubType>Code</SubType>
|
||||
</ClInclude>
|
||||
<ClInclude Include="EditColorScheme.h">
|
||||
<DependentUpon>EditColorScheme.xaml</DependentUpon>
|
||||
<SubType>Code</SubType>
|
||||
@ -197,6 +201,9 @@
|
||||
<Page Include="NullableColorPicker.xaml">
|
||||
<SubType>Designer</SubType>
|
||||
</Page>
|
||||
<Page Include="IconPicker.xaml">
|
||||
<SubType>Designer</SubType>
|
||||
</Page>
|
||||
<Page Include="EditColorScheme.xaml">
|
||||
<SubType>Designer</SubType>
|
||||
</Page>
|
||||
@ -273,6 +280,10 @@
|
||||
<DependentUpon>NullableColorPicker.xaml</DependentUpon>
|
||||
<SubType>Code</SubType>
|
||||
</ClCompile>
|
||||
<ClCompile Include="IconPicker.cpp">
|
||||
<DependentUpon>IconPicker.xaml</DependentUpon>
|
||||
<SubType>Code</SubType>
|
||||
</ClCompile>
|
||||
<ClCompile Include="EditColorScheme.cpp">
|
||||
<DependentUpon>EditColorScheme.xaml</DependentUpon>
|
||||
<SubType>Code</SubType>
|
||||
@ -404,6 +415,10 @@
|
||||
<DependentUpon>NullableColorPicker.xaml</DependentUpon>
|
||||
<SubType>Code</SubType>
|
||||
</Midl>
|
||||
<Midl Include="IconPicker.idl">
|
||||
<DependentUpon>IconPicker.xaml</DependentUpon>
|
||||
<SubType>Code</SubType>
|
||||
</Midl>
|
||||
<Midl Include="EditColorScheme.idl">
|
||||
<DependentUpon>EditColorScheme.xaml</DependentUpon>
|
||||
<SubType>Code</SubType>
|
||||
|
||||
@ -55,6 +55,7 @@
|
||||
<Page Include="AddProfile.xaml" />
|
||||
<Page Include="KeyChordListener.xaml" />
|
||||
<Page Include="NullableColorPicker.xaml" />
|
||||
<Page Include="IconPicker.xaml" />
|
||||
<Page Include="NewTabMenu.xaml" />
|
||||
</ItemGroup>
|
||||
</Project>
|
||||
@ -5,6 +5,7 @@
|
||||
#include "NewTabMenu.h"
|
||||
#include "NavigateToPageArgs.g.h"
|
||||
#include "NewTabMenu.g.cpp"
|
||||
#include "NavigateToPageArgs.g.h"
|
||||
#include "NewTabMenuEntryTemplateSelector.g.cpp"
|
||||
#include "EnumEntry.h"
|
||||
|
||||
@ -25,9 +26,8 @@ namespace winrt::Microsoft::Terminal::Settings::Editor::implementation
|
||||
// but the XAML compiler can't find NewTabMenuListView when we try that. Rather than copying the list of selected items over
|
||||
// to the view model, we'll just do this instead (much simpler).
|
||||
NewTabMenuListView().SelectionChanged([this](auto&&, auto&&) {
|
||||
const auto list = NewTabMenuListView();
|
||||
MoveToFolderButton().IsEnabled(list.SelectedItems().Size() > 0);
|
||||
DeleteMultipleButton().IsEnabled(list.SelectedItems().Size() > 0);
|
||||
MoveToFolderButton().IsEnabled(NewTabMenuListView().SelectedItems().Size() > 0);
|
||||
DeleteMultipleButton().IsEnabled(NewTabMenuListView().SelectedItems().Size() > 0);
|
||||
});
|
||||
|
||||
Automation::AutomationProperties::SetName(MoveToFolderButton(), RS_(L"NewTabMenu_MoveToFolderTextBlock/Text"));
|
||||
@ -44,7 +44,7 @@ namespace winrt::Microsoft::Terminal::Settings::Editor::implementation
|
||||
{
|
||||
const auto args = e.Parameter().as<Editor::NavigateToPageArgs>();
|
||||
_ViewModel = args.ViewModel().as<Editor::NewTabMenuViewModel>();
|
||||
|
||||
_weakWindowRoot = args.WindowRoot();
|
||||
BringIntoViewWhenLoaded(args.ElementToFocus());
|
||||
|
||||
TraceLoggingWrite(
|
||||
|
||||
@ -38,11 +38,13 @@ namespace winrt::Microsoft::Terminal::Settings::Editor::implementation
|
||||
void AddFolderNameTextBox_KeyDown(const winrt::Windows::Foundation::IInspectable& sender, const winrt::Windows::UI::Xaml::Input::KeyRoutedEventArgs& e);
|
||||
void AddFolderNameTextBox_TextChanged(const winrt::Windows::Foundation::IInspectable& sender, const winrt::Windows::UI::Xaml::Controls::TextChangedEventArgs& e);
|
||||
|
||||
Editor::IHostedInWindow WindowRoot() const noexcept { return _weakWindowRoot.get(); }
|
||||
WINRT_CALLBACK(PropertyChanged, Windows::UI::Xaml::Data::PropertyChangedEventHandler);
|
||||
WINRT_OBSERVABLE_PROPERTY(Editor::NewTabMenuViewModel, ViewModel, _PropertyChangedHandlers, nullptr);
|
||||
|
||||
private:
|
||||
Editor::NewTabMenuEntryViewModel _draggedEntry{ nullptr };
|
||||
winrt::weak_ref<Editor::IHostedInWindow> _weakWindowRoot;
|
||||
|
||||
void _ScrollToEntry(const Editor::NewTabMenuEntryViewModel& entry);
|
||||
};
|
||||
|
||||
@ -9,6 +9,7 @@ namespace Microsoft.Terminal.Settings.Editor
|
||||
{
|
||||
NewTabMenu();
|
||||
NewTabMenuViewModel ViewModel { get; };
|
||||
IHostedInWindow WindowRoot { get; };
|
||||
}
|
||||
|
||||
[default_interface] runtimeclass NewTabMenuEntryTemplateSelector : Windows.UI.Xaml.Controls.DataTemplateSelector
|
||||
|
||||
@ -319,32 +319,51 @@
|
||||
Visibility="{x:Bind ViewModel.IsFolderView, Mode=OneWay}">
|
||||
<TextBlock x:Uid="NewTabMenu_CurrentFolderTextBlock"
|
||||
Style="{StaticResource TextBlockSubHeaderStyle}" />
|
||||
|
||||
<!-- TODO GH #18281: Icon -->
|
||||
<!-- Once PR #17965 merges, we can add that kind of control to set an icon -->
|
||||
|
||||
<!-- Name -->
|
||||
<local:SettingContainer x:Name="CurrentFolderName"
|
||||
x:Uid="NewTabMenu_CurrentFolderName"
|
||||
Grid.Row="0"
|
||||
CurrentValue="{x:Bind ViewModel.CurrentFolderName, Mode=OneWay}"
|
||||
Style="{StaticResource ExpanderSettingContainerStyle}">
|
||||
<TextBox Style="{StaticResource TextBoxSettingStyle}"
|
||||
Text="{x:Bind ViewModel.CurrentFolderName, Mode=TwoWay}" />
|
||||
</local:SettingContainer>
|
||||
|
||||
<!-- Icon -->
|
||||
<local:SettingContainer x:Uid="NewTabMenu_CurrentFolderIcon"
|
||||
CurrentValueAccessibleName="{x:Bind ViewModel.CurrentFolderLocalizedIcon, Mode=OneWay}"
|
||||
Style="{StaticResource ExpanderSettingContainerStyleWithComplexPreview}">
|
||||
<local:SettingContainer.CurrentValue>
|
||||
<Grid>
|
||||
<ContentControl Width="16"
|
||||
Height="16"
|
||||
Content="{x:Bind ViewModel.CurrentFolderIconPreview, Mode=OneWay}"
|
||||
IsTabStop="False"
|
||||
Visibility="{x:Bind mtu:Converters.InvertedBooleanToVisibility(ViewModel.CurrentFolderUsingNoIcon), Mode=OneWay}" />
|
||||
<TextBlock Margin="0,0,0,0"
|
||||
HorizontalAlignment="Right"
|
||||
VerticalAlignment="Center"
|
||||
FontFamily="Segoe UI, Segoe Fluent Icons, Segoe MDL2 Assets"
|
||||
Style="{StaticResource SettingsPageItemDescriptionStyle}"
|
||||
Text="{x:Bind ViewModel.CurrentFolderLocalizedIcon, Mode=OneWay}"
|
||||
Visibility="{x:Bind ViewModel.CurrentFolderUsingNoIcon, Mode=OneWay}" />
|
||||
</Grid>
|
||||
</local:SettingContainer.CurrentValue>
|
||||
<local:SettingContainer.Content>
|
||||
<local:IconPicker CurrentIconPath="{x:Bind ViewModel.CurrentFolderIconPath, Mode=TwoWay}"
|
||||
WindowRoot="{x:Bind WindowRoot, Mode=OneWay}" />
|
||||
</local:SettingContainer.Content>
|
||||
</local:SettingContainer>
|
||||
|
||||
<!-- Inlining -->
|
||||
<local:SettingContainer x:Name="CurrentFolderInlining"
|
||||
x:Uid="NewTabMenu_CurrentFolderInlining"
|
||||
Grid.Row="1">
|
||||
x:Uid="NewTabMenu_CurrentFolderInlining">
|
||||
<ToggleSwitch IsOn="{x:Bind ViewModel.CurrentFolderInlining, Mode=TwoWay}"
|
||||
Style="{StaticResource ToggleSwitchInExpanderStyle}" />
|
||||
</local:SettingContainer>
|
||||
|
||||
<!-- Allow Empty -->
|
||||
<local:SettingContainer x:Name="CurrentFolderAllowEmpty"
|
||||
x:Uid="NewTabMenu_CurrentFolderAllowEmpty"
|
||||
Grid.Row="2">
|
||||
x:Uid="NewTabMenu_CurrentFolderAllowEmpty">
|
||||
<ToggleSwitch IsOn="{x:Bind ViewModel.CurrentFolderAllowEmpty, Mode=TwoWay}"
|
||||
Style="{StaticResource ToggleSwitchInExpanderStyle}" />
|
||||
</local:SettingContainer>
|
||||
|
||||
@ -3,6 +3,7 @@
|
||||
|
||||
#include "pch.h"
|
||||
#include "NewTabMenuViewModel.h"
|
||||
#include "IconPicker.h"
|
||||
|
||||
#include "NewTabMenuViewModel.g.cpp"
|
||||
#include "FolderTreeViewEntry.g.cpp"
|
||||
@ -160,6 +161,10 @@ namespace winrt::Microsoft::Terminal::Settings::Editor::implementation
|
||||
// FolderTree needs to be updated when a folder is renamed
|
||||
_folderTreeCache = nullptr;
|
||||
}
|
||||
else if (viewModelProperty == L"Icon")
|
||||
{
|
||||
_NotifyChanges(L"CurrentFolderIconPreview", L"CurrentFolderLocalizedIcon", L"CurrentFolderIconPath", L"CurrentFolderUsingNoIcon");
|
||||
}
|
||||
}
|
||||
|
||||
hstring NewTabMenuViewModel::CurrentFolderName() const
|
||||
@ -216,6 +221,60 @@ namespace winrt::Microsoft::Terminal::Settings::Editor::implementation
|
||||
}
|
||||
}
|
||||
|
||||
Windows::UI::Xaml::Controls::IconElement NewTabMenuViewModel::CurrentFolderIconPreview() const
|
||||
{
|
||||
if (!_CurrentFolder)
|
||||
{
|
||||
return nullptr;
|
||||
}
|
||||
// IconWUX sets the icon width/height to 32 by default
|
||||
auto icon = Microsoft::Terminal::UI::IconPathConverter::IconWUX(_CurrentFolder.Icon());
|
||||
icon.Width(16);
|
||||
icon.Height(16);
|
||||
return icon;
|
||||
}
|
||||
|
||||
winrt::hstring NewTabMenuViewModel::CurrentFolderLocalizedIcon() const
|
||||
{
|
||||
if (!_CurrentFolder)
|
||||
{
|
||||
return {};
|
||||
}
|
||||
if (CurrentFolderUsingNoIcon())
|
||||
{
|
||||
return RS_(L"IconPicker_IconTypeNone");
|
||||
}
|
||||
return _CurrentFolder.Icon(); // For display as a string
|
||||
}
|
||||
|
||||
winrt::hstring NewTabMenuViewModel::CurrentFolderIconPath() const
|
||||
{
|
||||
if (!_CurrentFolder)
|
||||
{
|
||||
return {};
|
||||
}
|
||||
return _CurrentFolder.Icon();
|
||||
}
|
||||
|
||||
void NewTabMenuViewModel::CurrentFolderIconPath(const winrt::hstring& path)
|
||||
{
|
||||
if (_CurrentFolder && _CurrentFolder.Icon() != path)
|
||||
{
|
||||
_CurrentFolder.Icon(path);
|
||||
_NotifyChanges(L"CurrentFolderIconPreview", L"CurrentFolderLocalizedIcon", L"CurrentFolderIconPath", L"CurrentFolderUsingNoIcon");
|
||||
}
|
||||
}
|
||||
|
||||
bool NewTabMenuViewModel::CurrentFolderUsingNoIcon() const noexcept
|
||||
{
|
||||
if (!_CurrentFolder)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
const auto icon{ _CurrentFolder.Icon() };
|
||||
return icon.empty() || icon == IconPicker::HideIconValue;
|
||||
}
|
||||
|
||||
Windows::Foundation::Collections::IObservableVector<Editor::NewTabMenuEntryViewModel> NewTabMenuViewModel::CurrentView() const
|
||||
{
|
||||
if (!_CurrentFolder)
|
||||
|
||||
@ -47,6 +47,12 @@ namespace winrt::Microsoft::Terminal::Settings::Editor::implementation
|
||||
bool CurrentFolderAllowEmpty() const;
|
||||
void CurrentFolderAllowEmpty(bool value);
|
||||
|
||||
Windows::UI::Xaml::Controls::IconElement CurrentFolderIconPreview() const;
|
||||
winrt::hstring CurrentFolderLocalizedIcon() const;
|
||||
winrt::hstring CurrentFolderIconPath() const;
|
||||
void CurrentFolderIconPath(const winrt::hstring& path);
|
||||
bool CurrentFolderUsingNoIcon() const noexcept;
|
||||
|
||||
Windows::Foundation::Collections::IObservableVector<Model::Profile> AvailableProfiles() const { return _Settings.AllProfiles(); }
|
||||
Windows::Foundation::Collections::IObservableVector<Editor::FolderTreeViewEntry> FolderTree() const;
|
||||
Windows::Foundation::Collections::IObservableVector<Editor::FolderEntryViewModel> FolderTreeFlatList() const;
|
||||
@ -136,6 +142,11 @@ namespace winrt::Microsoft::Terminal::Settings::Editor::implementation
|
||||
void Inlining(bool value);
|
||||
|
||||
hstring Icon() const { return _FolderEntry.Icon().Path(); }
|
||||
void Icon(const hstring& value)
|
||||
{
|
||||
_FolderEntry.Icon(Model::MediaResourceHelper::FromString(value));
|
||||
_NotifyChanges(L"Icon");
|
||||
}
|
||||
|
||||
GETSET_OBSERVABLE_PROJECTED_SETTING(_FolderEntry, Name);
|
||||
GETSET_OBSERVABLE_PROJECTED_SETTING(_FolderEntry, AllowEmpty);
|
||||
|
||||
@ -41,6 +41,11 @@ namespace Microsoft.Terminal.Settings.Editor
|
||||
String ProfileMatcherCommandline;
|
||||
String AddFolderName;
|
||||
|
||||
Windows.UI.Xaml.Controls.IconElement CurrentFolderIconPreview { get; };
|
||||
String CurrentFolderLocalizedIcon { get; };
|
||||
String CurrentFolderIconPath;
|
||||
Boolean CurrentFolderUsingNoIcon { get; };
|
||||
|
||||
void RequestReorderEntry(NewTabMenuEntryViewModel vm, Boolean goingUp);
|
||||
void RequestDeleteEntry(NewTabMenuEntryViewModel vm);
|
||||
void RequestMoveEntriesToFolder(IVector<NewTabMenuEntryViewModel> entries, FolderEntryViewModel folderEntry);
|
||||
@ -83,7 +88,7 @@ namespace Microsoft.Terminal.Settings.Editor
|
||||
FolderEntryViewModel(Microsoft.Terminal.Settings.Model.FolderEntry folderEntry, Microsoft.Terminal.Settings.Model.CascadiaSettings settings);
|
||||
|
||||
String Name;
|
||||
String Icon { get; };
|
||||
String Icon;
|
||||
Boolean Inlining;
|
||||
Boolean AllowEmpty;
|
||||
IObservableVector<Microsoft.Terminal.Settings.Editor.NewTabMenuEntryViewModel> Entries;
|
||||
|
||||
@ -4,14 +4,13 @@
|
||||
#include "pch.h"
|
||||
#include "ProfileViewModel.h"
|
||||
#include "ProfileViewModel.g.cpp"
|
||||
#include "EnumEntry.h"
|
||||
#include "Appearances.h"
|
||||
#include "EnumEntry.h"
|
||||
#include "IconPicker.h"
|
||||
|
||||
#include "../WinRTUtils/inc/Utils.h"
|
||||
#include "../../renderer/base/FontCache.h"
|
||||
#include "../TerminalSettingsAppAdapterLib/TerminalSettings.h"
|
||||
#include "SegoeFluentIconList.h"
|
||||
#include "../../types/inc/utils.hpp"
|
||||
|
||||
using namespace winrt::Windows::UI::Text;
|
||||
using namespace winrt::Windows::UI::Xaml;
|
||||
@ -28,9 +27,6 @@ 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 };
|
||||
Windows::Foundation::Collections::IObservableVector<Editor::EnumEntry> ProfileViewModel::_BuiltInIcons{ nullptr };
|
||||
|
||||
static constexpr std::wstring_view HideIconValue{ L"none" };
|
||||
|
||||
ProfileViewModel::ProfileViewModel(const Model::Profile& profile, const Model::CascadiaSettings& appSettings, const Windows::UI::Core::CoreDispatcher& dispatcher) :
|
||||
_profile{ profile },
|
||||
@ -47,17 +43,6 @@ namespace winrt::Microsoft::Terminal::Settings::Editor::implementation
|
||||
|
||||
_InitializeCurrentBellSounds();
|
||||
|
||||
// set up IconTypes
|
||||
std::vector<IInspectable> iconTypes;
|
||||
iconTypes.reserve(4);
|
||||
iconTypes.emplace_back(make<EnumEntry>(RS_(L"Profile_IconTypeNone"), box_value(IconType::None)));
|
||||
iconTypes.emplace_back(make<EnumEntry>(RS_(L"Profile_IconTypeFontIcon"), box_value(IconType::FontIcon)));
|
||||
iconTypes.emplace_back(make<EnumEntry>(RS_(L"Profile_IconTypeEmoji"), box_value(IconType::Emoji)));
|
||||
iconTypes.emplace_back(make<EnumEntry>(RS_(L"Profile_IconTypeImage"), box_value(IconType::Image)));
|
||||
_IconTypes = winrt::single_threaded_vector<IInspectable>(std::move(iconTypes));
|
||||
_DeduceCurrentIconType();
|
||||
_DeduceCurrentBuiltInIcon();
|
||||
|
||||
// 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.
|
||||
@ -92,32 +77,15 @@ namespace winrt::Microsoft::Terminal::Settings::Editor::implementation
|
||||
}
|
||||
else if (viewModelProperty == L"Icon")
|
||||
{
|
||||
// _DeduceCurrentIconType() ends with a "CurrentIconType" notification
|
||||
// so we don't need to call _UpdateIconPreview() here
|
||||
_DeduceCurrentIconType();
|
||||
// The icon changed; let's re-evaluate it with its new context.
|
||||
_appSettings.ResolveMediaResources();
|
||||
}
|
||||
else if (viewModelProperty == L"CurrentIconType")
|
||||
{
|
||||
// "Using*" handles the visibility of the IconType-related UI.
|
||||
// The others propagate the rendered icon into a preview (i.e. nav view, container item)
|
||||
_NotifyChanges(L"UsingNoIcon",
|
||||
L"UsingBuiltInIcon",
|
||||
L"UsingEmojiIcon",
|
||||
L"UsingImageIcon",
|
||||
L"LocalizedIcon",
|
||||
|
||||
// Propagate the rendered icon into a preview (i.e. nav view, container item)
|
||||
_NotifyChanges(L"LocalizedIcon",
|
||||
L"IconPreview",
|
||||
L"IconPath",
|
||||
L"EvaluatedIcon");
|
||||
}
|
||||
else if (viewModelProperty == L"CurrentBuiltInIcon")
|
||||
{
|
||||
IconPath(unbox_value<hstring>(_CurrentBuiltInIcon.EnumValue()));
|
||||
}
|
||||
else if (viewModelProperty == L"CurrentEmojiIcon")
|
||||
{
|
||||
IconPath(CurrentEmojiIcon());
|
||||
L"EvaluatedIcon",
|
||||
L"UsingNoIcon");
|
||||
}
|
||||
else if (viewModelProperty == L"CurrentBellSounds")
|
||||
{
|
||||
@ -190,61 +158,6 @@ namespace winrt::Microsoft::Terminal::Settings::Editor::implementation
|
||||
_defaultAppearanceViewModel.IsDefault(true);
|
||||
}
|
||||
|
||||
void ProfileViewModel::_UpdateBuiltInIcons()
|
||||
{
|
||||
std::vector<Editor::EnumEntry> builtInIcons;
|
||||
for (auto& [val, name] : s_SegoeFluentIcons)
|
||||
{
|
||||
builtInIcons.emplace_back(make<EnumEntry>(hstring{ name }, box_value(val)));
|
||||
}
|
||||
_BuiltInIcons = single_threaded_observable_vector<Editor::EnumEntry>(std::move(builtInIcons));
|
||||
}
|
||||
|
||||
void ProfileViewModel::_DeduceCurrentIconType()
|
||||
{
|
||||
const auto profileIcon = IconPath();
|
||||
if (profileIcon == HideIconValue)
|
||||
{
|
||||
_currentIconType = _IconTypes.GetAt(0);
|
||||
}
|
||||
else if (profileIcon.size() == 1 && (L'\uE700' <= til::at(profileIcon, 0) && til::at(profileIcon, 0) <= L'\uF8B3'))
|
||||
{
|
||||
_currentIconType = _IconTypes.GetAt(1);
|
||||
_DeduceCurrentBuiltInIcon();
|
||||
}
|
||||
else if (::Microsoft::Console::Utils::IsLikelyToBeEmojiOrSymbolIcon(profileIcon))
|
||||
{
|
||||
// We already did a range check for MDL2 Assets in the previous one,
|
||||
// so if we're out of that range but still short, assume we're an emoji
|
||||
_currentIconType = _IconTypes.GetAt(2);
|
||||
}
|
||||
else
|
||||
{
|
||||
_currentIconType = _IconTypes.GetAt(3);
|
||||
}
|
||||
_NotifyChanges(L"CurrentIconType");
|
||||
}
|
||||
|
||||
void ProfileViewModel::_DeduceCurrentBuiltInIcon()
|
||||
{
|
||||
if (!_BuiltInIcons)
|
||||
{
|
||||
_UpdateBuiltInIcons();
|
||||
}
|
||||
const auto profileIcon = IconPath();
|
||||
for (uint32_t i = 0; i < _BuiltInIcons.Size(); i++)
|
||||
{
|
||||
const auto& builtIn = _BuiltInIcons.GetAt(i);
|
||||
if (profileIcon == unbox_value<hstring>(builtIn.EnumValue()))
|
||||
{
|
||||
_CurrentBuiltInIcon = builtIn;
|
||||
return;
|
||||
}
|
||||
}
|
||||
_CurrentBuiltInIcon = _BuiltInIcons.GetAt(0);
|
||||
_NotifyChanges(L"CurrentBuiltInIcon");
|
||||
}
|
||||
|
||||
void ProfileViewModel::LeftPadding(double value) noexcept
|
||||
{
|
||||
if (std::abs(_parsedPadding.Left - value) >= .0001)
|
||||
@ -636,9 +549,9 @@ namespace winrt::Microsoft::Terminal::Settings::Editor::implementation
|
||||
|
||||
winrt::hstring ProfileViewModel::LocalizedIcon() const
|
||||
{
|
||||
if (_currentIconType && unbox_value<IconType>(_currentIconType.as<Editor::EnumEntry>().EnumValue()) == IconType::None)
|
||||
if (UsingNoIcon())
|
||||
{
|
||||
return RS_(L"Profile_IconTypeNone");
|
||||
return RS_(L"IconPicker_IconTypeNone");
|
||||
}
|
||||
return IconPath(); // For display as a string
|
||||
}
|
||||
@ -652,83 +565,10 @@ namespace winrt::Microsoft::Terminal::Settings::Editor::implementation
|
||||
return icon;
|
||||
}
|
||||
|
||||
void ProfileViewModel::CurrentIconType(const Windows::Foundation::IInspectable& value)
|
||||
bool ProfileViewModel::UsingNoIcon() const noexcept
|
||||
{
|
||||
if (_currentIconType != value)
|
||||
{
|
||||
// Switching from...
|
||||
if (_currentIconType && unbox_value<IconType>(_currentIconType.as<Editor::EnumEntry>().EnumValue()) == IconType::Image)
|
||||
{
|
||||
// Stash the current value of Icon. If the user
|
||||
// switches out of then back to IconType::Image, we want
|
||||
// the path that we display in the text box to remain unchanged.
|
||||
_lastIconPath = IconPath();
|
||||
}
|
||||
|
||||
// Set the member here instead of after setting Icon() below!
|
||||
// We have an Icon property changed handler defined for when we discard changes.
|
||||
// Inadvertently, that means that we call this setter again.
|
||||
// Setting the member here means that we early exit at the beginning of the function
|
||||
// because _currentIconType == value.
|
||||
_currentIconType = value;
|
||||
|
||||
// Switched to...
|
||||
switch (unbox_value<IconType>(value.as<Editor::EnumEntry>().EnumValue()))
|
||||
{
|
||||
case IconType::None:
|
||||
{
|
||||
IconPath(winrt::hstring{ HideIconValue });
|
||||
break;
|
||||
}
|
||||
case IconType::Image:
|
||||
{
|
||||
if (!_lastIconPath.empty())
|
||||
{
|
||||
// Conversely, if we switch to Image,
|
||||
// retrieve that saved value and apply it
|
||||
IconPath(_lastIconPath);
|
||||
}
|
||||
break;
|
||||
}
|
||||
case IconType::FontIcon:
|
||||
{
|
||||
if (_CurrentBuiltInIcon)
|
||||
{
|
||||
IconPath(unbox_value<hstring>(_CurrentBuiltInIcon.EnumValue()));
|
||||
}
|
||||
break;
|
||||
}
|
||||
case IconType::Emoji:
|
||||
{
|
||||
// Don't set Icon here!
|
||||
// Clear out the text box so we direct the user to use the emoji picker.
|
||||
CurrentEmojiIcon({});
|
||||
}
|
||||
}
|
||||
// We're not using the VM's Icon() setter above,
|
||||
// so notify HasIcon changed manually
|
||||
_NotifyChanges(L"CurrentIconType", L"HasIcon");
|
||||
}
|
||||
}
|
||||
|
||||
bool ProfileViewModel::UsingNoIcon() const
|
||||
{
|
||||
return _currentIconType == _IconTypes.GetAt(0);
|
||||
}
|
||||
|
||||
bool ProfileViewModel::UsingBuiltInIcon() const
|
||||
{
|
||||
return _currentIconType == _IconTypes.GetAt(1);
|
||||
}
|
||||
|
||||
bool ProfileViewModel::UsingEmojiIcon() const
|
||||
{
|
||||
return _currentIconType == _IconTypes.GetAt(2);
|
||||
}
|
||||
|
||||
bool ProfileViewModel::UsingImageIcon() const
|
||||
{
|
||||
return _currentIconType == _IconTypes.GetAt(3);
|
||||
const auto iconPath{ IconPath() };
|
||||
return iconPath.empty() || iconPath == IconPicker::HideIconValue;
|
||||
}
|
||||
|
||||
hstring ProfileViewModel::BellStylePreview() const
|
||||
|
||||
@ -33,7 +33,6 @@ namespace winrt::Microsoft::Terminal::Settings::Editor::implementation
|
||||
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 Windows::Foundation::Collections::IObservableVector<Editor::EnumEntry> BuiltInIcons() noexcept { return _BuiltInIcons; };
|
||||
|
||||
ProfileViewModel(const Model::Profile& profile, const Model::CascadiaSettings& settings, const Windows::UI::Core::CoreDispatcher& dispatcher);
|
||||
Control::IControlSettings TermSettings() const;
|
||||
@ -76,23 +75,15 @@ namespace winrt::Microsoft::Terminal::Settings::Editor::implementation
|
||||
{
|
||||
return _profile.Icon().Resolved();
|
||||
}
|
||||
Windows::Foundation::IInspectable CurrentIconType() const noexcept
|
||||
{
|
||||
return _currentIconType;
|
||||
}
|
||||
Windows::UI::Xaml::Controls::IconElement IconPreview() const;
|
||||
winrt::hstring LocalizedIcon() const;
|
||||
void CurrentIconType(const Windows::Foundation::IInspectable& value);
|
||||
bool UsingNoIcon() const;
|
||||
bool UsingBuiltInIcon() const;
|
||||
bool UsingEmojiIcon() const;
|
||||
bool UsingImageIcon() const;
|
||||
winrt::hstring IconPath() const { return _profile.Icon().Path(); }
|
||||
void IconPath(const winrt::hstring& path)
|
||||
{
|
||||
Icon(Model::MediaResourceHelper::FromString(path));
|
||||
_NotifyChanges(L"Icon", L"IconPath");
|
||||
}
|
||||
bool UsingNoIcon() const noexcept;
|
||||
|
||||
// starting directory
|
||||
hstring CurrentStartingDirectoryPreview() const;
|
||||
@ -124,8 +115,6 @@ namespace winrt::Microsoft::Terminal::Settings::Editor::implementation
|
||||
|
||||
VIEW_MODEL_OBSERVABLE_PROPERTY(ProfileSubPage, CurrentPage);
|
||||
VIEW_MODEL_OBSERVABLE_PROPERTY(Windows::Foundation::Collections::IObservableVector<Editor::BellSoundViewModel>, CurrentBellSounds);
|
||||
VIEW_MODEL_OBSERVABLE_PROPERTY(Editor::EnumEntry, CurrentBuiltInIcon, nullptr);
|
||||
VIEW_MODEL_OBSERVABLE_PROPERTY(hstring, CurrentEmojiIcon);
|
||||
|
||||
PERMANENT_OBSERVABLE_PROJECTED_SETTING(_profile, Guid);
|
||||
PERMANENT_OBSERVABLE_PROJECTED_SETTING(_profile, ConnectionType);
|
||||
@ -165,7 +154,6 @@ namespace winrt::Microsoft::Terminal::Settings::Editor::implementation
|
||||
WINRT_PROPERTY(bool, IsBaseLayer, false);
|
||||
WINRT_PROPERTY(bool, FocusDeleteButton, false);
|
||||
WINRT_PROPERTY(hstring, ElementToFocus);
|
||||
WINRT_PROPERTY(Windows::Foundation::Collections::IVector<Windows::Foundation::IInspectable>, IconTypes);
|
||||
GETSET_BINDABLE_ENUM_SETTING(AntiAliasingMode, Microsoft::Terminal::Control::TextAntialiasingMode, AntialiasingMode);
|
||||
GETSET_BINDABLE_ENUM_SETTING(CloseOnExitMode, Microsoft::Terminal::Settings::Model::CloseOnExitMode, CloseOnExit);
|
||||
GETSET_BINDABLE_ENUM_SETTING(ScrollState, Microsoft::Terminal::Control::ScrollbarState, ScrollState);
|
||||
@ -176,8 +164,6 @@ namespace winrt::Microsoft::Terminal::Settings::Editor::implementation
|
||||
winrt::guid _originalProfileGuid{};
|
||||
winrt::hstring _lastBgImagePath;
|
||||
winrt::hstring _lastStartingDirectoryPath;
|
||||
winrt::hstring _lastIconPath;
|
||||
Windows::Foundation::IInspectable _currentIconType{};
|
||||
Editor::AppearanceViewModel _defaultAppearanceViewModel;
|
||||
Windows::UI::Core::CoreDispatcher _dispatcher;
|
||||
|
||||
@ -188,13 +174,9 @@ namespace winrt::Microsoft::Terminal::Settings::Editor::implementation
|
||||
void _MarkDuplicateBellSoundDirectories();
|
||||
static Windows::Foundation::Collections::IObservableVector<Editor::Font> _MonospaceFontList;
|
||||
static Windows::Foundation::Collections::IObservableVector<Editor::Font> _FontList;
|
||||
static Windows::Foundation::Collections::IObservableVector<Editor::EnumEntry> _BuiltInIcons;
|
||||
|
||||
Model::CascadiaSettings _appSettings;
|
||||
Editor::AppearanceViewModel _unfocusedAppearanceViewModel;
|
||||
void _UpdateBuiltInIcons();
|
||||
void _DeduceCurrentIconType();
|
||||
void _DeduceCurrentBuiltInIcon();
|
||||
};
|
||||
|
||||
struct DeleteProfileEventArgs :
|
||||
|
||||
@ -36,14 +36,6 @@ namespace Microsoft.Terminal.Settings.Editor
|
||||
Advanced = 3
|
||||
};
|
||||
|
||||
enum IconType
|
||||
{
|
||||
None = 0,
|
||||
FontIcon,
|
||||
Image,
|
||||
Emoji
|
||||
};
|
||||
|
||||
runtimeclass ProfileViewModel : Windows.UI.Xaml.Data.INotifyPropertyChanged
|
||||
{
|
||||
event Windows.Foundation.TypedEventHandler<ProfileViewModel, DeleteProfileEventArgs> DeleteProfileRequested;
|
||||
@ -101,17 +93,8 @@ namespace Microsoft.Terminal.Settings.Editor
|
||||
Windows.UI.Xaml.Controls.IconElement IconPreview { get; };
|
||||
String EvaluatedIcon { get; };
|
||||
String LocalizedIcon { get; };
|
||||
String CurrentEmojiIcon;
|
||||
IInspectable CurrentIconType;
|
||||
Windows.Foundation.Collections.IVector<IInspectable> IconTypes { get; };
|
||||
Boolean UsingNoIcon { get; };
|
||||
Boolean UsingBuiltInIcon { get; };
|
||||
Boolean UsingEmojiIcon { get; };
|
||||
Boolean UsingImageIcon { get; };
|
||||
String IconPath;
|
||||
|
||||
EnumEntry CurrentBuiltInIcon;
|
||||
Windows.Foundation.Collections.IObservableVector<EnumEntry> BuiltInIcons { get; };
|
||||
Boolean UsingNoIcon { get; };
|
||||
|
||||
String TabTitlePreview { get; };
|
||||
String AnswerbackMessagePreview { get; };
|
||||
|
||||
@ -27,7 +27,7 @@ namespace winrt::Microsoft::Terminal::Settings::Editor::implementation
|
||||
{
|
||||
const auto args = e.Parameter().as<Editor::NavigateToPageArgs>();
|
||||
_Profile = args.ViewModel().as<Editor::ProfileViewModel>();
|
||||
_windowRoot = args.WindowRoot();
|
||||
_weakWindowRoot = args.WindowRoot();
|
||||
BringIntoViewWhenLoaded(args.ElementToFocus());
|
||||
|
||||
TraceLoggingWrite(
|
||||
@ -98,7 +98,12 @@ namespace winrt::Microsoft::Terminal::Settings::Editor::implementation
|
||||
{ L"All Files (*.*)", L"*.*" }
|
||||
};
|
||||
|
||||
const auto parentHwnd{ reinterpret_cast<HWND>(WindowRoot().GetHostingWindow()) };
|
||||
const auto windowRoot = WindowRoot();
|
||||
if (!windowRoot)
|
||||
{
|
||||
co_return;
|
||||
}
|
||||
const auto parentHwnd{ reinterpret_cast<HWND>(windowRoot.GetHostingWindow()) };
|
||||
auto file = co_await OpenFilePicker(parentHwnd, [](auto&& dialog) {
|
||||
try
|
||||
{
|
||||
|
||||
@ -22,12 +22,12 @@ namespace winrt::Microsoft::Terminal::Settings::Editor::implementation
|
||||
void BellSoundAdd_Click(const Windows::Foundation::IInspectable& sender, const Windows::UI::Xaml::RoutedEventArgs& e);
|
||||
|
||||
til::property_changed_event PropertyChanged;
|
||||
Editor::IHostedInWindow WindowRoot() { return _windowRoot; };
|
||||
Editor::IHostedInWindow WindowRoot() const noexcept { return _weakWindowRoot.get(); };
|
||||
WINRT_PROPERTY(Editor::ProfileViewModel, Profile, nullptr);
|
||||
|
||||
private:
|
||||
Windows::UI::Xaml::Data::INotifyPropertyChanged::PropertyChanged_revoker _ViewModelChangedRevoker;
|
||||
Editor::IHostedInWindow _windowRoot;
|
||||
winrt::weak_ref<Editor::IHostedInWindow> _weakWindowRoot;
|
||||
winrt::Windows::Media::Playback::MediaPlayer _bellPlayer{ nullptr };
|
||||
bool _bellPlayerCreated{ false };
|
||||
|
||||
|
||||
@ -27,7 +27,7 @@ namespace winrt::Microsoft::Terminal::Settings::Editor::implementation
|
||||
{
|
||||
const auto args = e.Parameter().as<Editor::NavigateToPageArgs>();
|
||||
_Profile = args.ViewModel().as<Editor::ProfileViewModel>();
|
||||
_windowRoot = args.WindowRoot();
|
||||
_weakWindowRoot = args.WindowRoot();
|
||||
|
||||
// Settings are stored in Profiles_Appearance and Appearances.
|
||||
// We use the "App." prefix to indicate if it's in Appearances,
|
||||
|
||||
@ -22,7 +22,7 @@ namespace winrt::Microsoft::Terminal::Settings::Editor::implementation
|
||||
void CreateUnfocusedAppearance_Click(const Windows::Foundation::IInspectable& sender, const Windows::UI::Xaml::RoutedEventArgs& e);
|
||||
void DeleteUnfocusedAppearance_Click(const Windows::Foundation::IInspectable& sender, const Windows::UI::Xaml::RoutedEventArgs& e);
|
||||
|
||||
Editor::IHostedInWindow WindowRoot() { return _windowRoot; };
|
||||
Editor::IHostedInWindow WindowRoot() const noexcept { return _weakWindowRoot.get(); };
|
||||
|
||||
til::property_changed_event PropertyChanged;
|
||||
WINRT_PROPERTY(Editor::ProfileViewModel, Profile, nullptr);
|
||||
@ -35,7 +35,7 @@ namespace winrt::Microsoft::Terminal::Settings::Editor::implementation
|
||||
std::shared_ptr<ThrottledFunc<>> _updatePreviewControl;
|
||||
Windows::UI::Xaml::Data::INotifyPropertyChanged::PropertyChanged_revoker _ViewModelChangedRevoker;
|
||||
Windows::UI::Xaml::Data::INotifyPropertyChanged::PropertyChanged_revoker _AppearanceViewModelChangedRevoker;
|
||||
Editor::IHostedInWindow _windowRoot;
|
||||
winrt::weak_ref<Editor::IHostedInWindow> _weakWindowRoot;
|
||||
};
|
||||
};
|
||||
|
||||
|
||||
@ -31,7 +31,7 @@ namespace winrt::Microsoft::Terminal::Settings::Editor::implementation
|
||||
{
|
||||
const auto args = e.Parameter().as<Editor::NavigateToPageArgs>();
|
||||
_Profile = args.ViewModel().as<Editor::ProfileViewModel>();
|
||||
_windowRoot = args.WindowRoot();
|
||||
_weakWindowRoot = args.WindowRoot();
|
||||
BringIntoViewWhenLoaded(args.ElementToFocus());
|
||||
|
||||
// Check the use parent directory box if the starting directory is empty
|
||||
@ -114,7 +114,13 @@ 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>(_windowRoot.GetHostingWindow()) };
|
||||
|
||||
const auto windowRoot = WindowRoot();
|
||||
if (!windowRoot)
|
||||
{
|
||||
co_return;
|
||||
}
|
||||
const auto parentHwnd{ reinterpret_cast<HWND>(windowRoot.GetHostingWindow()) };
|
||||
auto path = co_await OpenFilePicker(parentHwnd, [](auto&& dialog) {
|
||||
THROW_IF_FAILED(dialog->SetClientGuid(clientGuidExecutables));
|
||||
try
|
||||
@ -134,22 +140,16 @@ namespace winrt::Microsoft::Terminal::Settings::Editor::implementation
|
||||
}
|
||||
}
|
||||
|
||||
safe_void_coroutine Profiles_Base::Icon_Click(const IInspectable&, const RoutedEventArgs&)
|
||||
{
|
||||
auto lifetime = get_strong();
|
||||
|
||||
const auto parentHwnd{ reinterpret_cast<HWND>(_windowRoot.GetHostingWindow()) };
|
||||
auto file = co_await OpenImagePicker(parentHwnd);
|
||||
if (!file.empty())
|
||||
{
|
||||
_Profile.IconPath(file);
|
||||
}
|
||||
}
|
||||
|
||||
safe_void_coroutine Profiles_Base::StartingDirectory_Click(const IInspectable&, const RoutedEventArgs&)
|
||||
{
|
||||
auto lifetime = get_strong();
|
||||
const auto parentHwnd{ reinterpret_cast<HWND>(_windowRoot.GetHostingWindow()) };
|
||||
|
||||
const auto windowRoot = WindowRoot();
|
||||
if (!windowRoot)
|
||||
{
|
||||
co_return;
|
||||
}
|
||||
const auto parentHwnd{ reinterpret_cast<HWND>(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));
|
||||
@ -170,77 +170,4 @@ namespace winrt::Microsoft::Terminal::Settings::Editor::implementation
|
||||
_Profile.StartingDirectory(folder);
|
||||
}
|
||||
}
|
||||
|
||||
IconSource Profiles_Base::BuiltInIconConverter(const IInspectable& iconVal)
|
||||
{
|
||||
return Microsoft::Terminal::UI::IconPathConverter::IconSourceWUX(unbox_value<hstring>(iconVal));
|
||||
}
|
||||
|
||||
void Profiles_Base::BuiltInIconPicker_GotFocus(const IInspectable& sender, const RoutedEventArgs& /*e*/)
|
||||
{
|
||||
_updateIconFilter({});
|
||||
sender.as<AutoSuggestBox>().IsSuggestionListOpen(true);
|
||||
}
|
||||
|
||||
void Profiles_Base::BuiltInIconPicker_QuerySubmitted(const AutoSuggestBox& /*sender*/, const AutoSuggestBoxQuerySubmittedEventArgs& e)
|
||||
{
|
||||
const auto iconEntry = unbox_value_or<EnumEntry>(e.ChosenSuggestion(), nullptr);
|
||||
if (!iconEntry)
|
||||
{
|
||||
return;
|
||||
}
|
||||
_Profile.CurrentBuiltInIcon(iconEntry);
|
||||
}
|
||||
|
||||
void Profiles_Base::BuiltInIconPicker_TextChanged(const AutoSuggestBox& sender, const AutoSuggestBoxTextChangedEventArgs& e)
|
||||
{
|
||||
if (e.Reason() != AutoSuggestionBoxTextChangeReason::UserInput)
|
||||
{
|
||||
return;
|
||||
}
|
||||
std::wstring_view filter{ sender.Text() };
|
||||
filter = til::trim(filter, L' ');
|
||||
_updateIconFilter(filter);
|
||||
}
|
||||
|
||||
void Profiles_Base::_updateIconFilter(std::wstring_view filter)
|
||||
{
|
||||
if (_iconFilter != filter)
|
||||
{
|
||||
_filteredBuiltInIcons = nullptr;
|
||||
_iconFilter = filter;
|
||||
_updateFilteredIconList();
|
||||
PropertyChanged.raise(*this, PropertyChangedEventArgs{ L"FilteredBuiltInIconList" });
|
||||
}
|
||||
}
|
||||
|
||||
Windows::Foundation::Collections::IObservableVector<Editor::EnumEntry> Profiles_Base::FilteredBuiltInIconList()
|
||||
{
|
||||
if (!_filteredBuiltInIcons)
|
||||
{
|
||||
_updateFilteredIconList();
|
||||
}
|
||||
return _filteredBuiltInIcons;
|
||||
}
|
||||
|
||||
void Profiles_Base::_updateFilteredIconList()
|
||||
{
|
||||
_filteredBuiltInIcons = ProfileViewModel::BuiltInIcons();
|
||||
if (_iconFilter.empty())
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
// Find matching icons and populate the filtered list
|
||||
std::vector<Editor::EnumEntry> filtered;
|
||||
filtered.reserve(_filteredBuiltInIcons.Size());
|
||||
for (const auto& icon : _filteredBuiltInIcons)
|
||||
{
|
||||
if (til::contains_linguistic_insensitive(icon.EnumName(), _iconFilter))
|
||||
{
|
||||
filtered.emplace_back(icon);
|
||||
}
|
||||
}
|
||||
_filteredBuiltInIcons = winrt::single_threaded_observable_vector(std::move(filtered));
|
||||
}
|
||||
}
|
||||
|
||||
@ -18,32 +18,20 @@ namespace winrt::Microsoft::Terminal::Settings::Editor::implementation
|
||||
void OnNavigatedFrom(const Windows::UI::Xaml::Navigation::NavigationEventArgs& e);
|
||||
|
||||
safe_void_coroutine StartingDirectory_Click(const Windows::Foundation::IInspectable& sender, const Windows::UI::Xaml::RoutedEventArgs& e);
|
||||
safe_void_coroutine Icon_Click(const Windows::Foundation::IInspectable& sender, const Windows::UI::Xaml::RoutedEventArgs& e);
|
||||
safe_void_coroutine Commandline_Click(const Windows::Foundation::IInspectable& sender, const Windows::UI::Xaml::RoutedEventArgs& e);
|
||||
void Appearance_Click(const Windows::Foundation::IInspectable& sender, const Windows::UI::Xaml::RoutedEventArgs& e);
|
||||
void Terminal_Click(const Windows::Foundation::IInspectable& sender, const Windows::UI::Xaml::RoutedEventArgs& e);
|
||||
void Advanced_Click(const Windows::Foundation::IInspectable& sender, const Windows::UI::Xaml::RoutedEventArgs& e);
|
||||
void DeleteConfirmation_Click(const Windows::Foundation::IInspectable& sender, const Windows::UI::Xaml::RoutedEventArgs& e);
|
||||
|
||||
Windows::Foundation::Collections::IObservableVector<Editor::EnumEntry> FilteredBuiltInIconList();
|
||||
void BuiltInIconPicker_GotFocus(const Windows::Foundation::IInspectable& sender, const Windows::UI::Xaml::RoutedEventArgs& e);
|
||||
void BuiltInIconPicker_TextChanged(const winrt::Windows::UI::Xaml::Controls::AutoSuggestBox& sender, const Windows::UI::Xaml::Controls::AutoSuggestBoxTextChangedEventArgs& e);
|
||||
void BuiltInIconPicker_QuerySubmitted(const winrt::Windows::UI::Xaml::Controls::AutoSuggestBox& sender, const Windows::UI::Xaml::Controls::AutoSuggestBoxQuerySubmittedEventArgs& e);
|
||||
|
||||
static Windows::UI::Xaml::Controls::IconSource BuiltInIconConverter(const Windows::Foundation::IInspectable& iconVal);
|
||||
|
||||
til::property_changed_event PropertyChanged;
|
||||
Editor::IHostedInWindow WindowRoot() const noexcept { return _weakWindowRoot.get(); }
|
||||
WINRT_PROPERTY(Editor::ProfileViewModel, Profile, nullptr);
|
||||
|
||||
private:
|
||||
Windows::UI::Xaml::Data::INotifyPropertyChanged::PropertyChanged_revoker _ViewModelChangedRevoker;
|
||||
winrt::Windows::UI::Xaml::Controls::SwapChainPanel::LayoutUpdated_revoker _layoutUpdatedRevoker;
|
||||
Editor::IHostedInWindow _windowRoot;
|
||||
Windows::Foundation::Collections::IObservableVector<Editor::EnumEntry> _filteredBuiltInIcons;
|
||||
std::wstring _iconFilter;
|
||||
|
||||
void _updateIconFilter(std::wstring_view filter);
|
||||
void _updateFilteredIconList();
|
||||
winrt::weak_ref<Editor::IHostedInWindow> _weakWindowRoot;
|
||||
};
|
||||
};
|
||||
|
||||
|
||||
@ -2,6 +2,7 @@
|
||||
// Licensed under the MIT license.
|
||||
|
||||
import "ProfileViewModel.idl";
|
||||
import "MainPage.idl";
|
||||
|
||||
namespace Microsoft.Terminal.Settings.Editor
|
||||
{
|
||||
@ -9,8 +10,6 @@ namespace Microsoft.Terminal.Settings.Editor
|
||||
{
|
||||
Profiles_Base();
|
||||
ProfileViewModel Profile { get; };
|
||||
Windows.Foundation.Collections.IObservableVector<EnumEntry> FilteredBuiltInIconList { get; };
|
||||
|
||||
static Windows.UI.Xaml.Controls.IconSource BuiltInIconConverter(IInspectable iconVal);
|
||||
IHostedInWindow WindowRoot { get; };
|
||||
}
|
||||
}
|
||||
|
||||
@ -124,82 +124,8 @@
|
||||
</Grid>
|
||||
</local:SettingContainer.CurrentValue>
|
||||
<local:SettingContainer.Content>
|
||||
<Grid ColumnSpacing="12">
|
||||
<Grid.ColumnDefinitions>
|
||||
<ColumnDefinition Width="auto" />
|
||||
<ColumnDefinition Width="*" />
|
||||
<ColumnDefinition Width="auto" />
|
||||
</Grid.ColumnDefinitions>
|
||||
|
||||
<!-- Icon Type -->
|
||||
<ComboBox x:Uid="Profile_IconType"
|
||||
Grid.Column="0"
|
||||
ItemsSource="{x:Bind Profile.IconTypes}"
|
||||
SelectedItem="{x:Bind Profile.CurrentIconType, Mode=TwoWay}">
|
||||
<ComboBox.ItemTemplate>
|
||||
<DataTemplate x:DataType="local:EnumEntry">
|
||||
<TextBlock Text="{x:Bind EnumName}" />
|
||||
</DataTemplate>
|
||||
</ComboBox.ItemTemplate>
|
||||
</ComboBox>
|
||||
|
||||
<!-- Built-In Icon -->
|
||||
<AutoSuggestBox x:Uid="Profile_BuiltInIcon"
|
||||
Grid.Column="1"
|
||||
GotFocus="BuiltInIconPicker_GotFocus"
|
||||
ItemsSource="{x:Bind FilteredBuiltInIconList, Mode=OneWay}"
|
||||
QuerySubmitted="BuiltInIconPicker_QuerySubmitted"
|
||||
Text="{x:Bind Profile.CurrentBuiltInIcon.EnumName, Mode=OneWay}"
|
||||
TextBoxStyle="{StaticResource TextBoxSettingStyle}"
|
||||
TextChanged="BuiltInIconPicker_TextChanged"
|
||||
Visibility="{x:Bind Profile.UsingBuiltInIcon, Mode=OneWay}">
|
||||
<AutoSuggestBox.ItemTemplate>
|
||||
<DataTemplate x:DataType="local:EnumEntry">
|
||||
<Grid ColumnSpacing="12">
|
||||
<Grid.ColumnDefinitions>
|
||||
<ColumnDefinition Width="16" />
|
||||
<ColumnDefinition Width="*" />
|
||||
</Grid.ColumnDefinitions>
|
||||
|
||||
<IconSourceElement Grid.Column="0"
|
||||
Width="16"
|
||||
Height="16"
|
||||
IconSource="{x:Bind local:Profiles_Base.BuiltInIconConverter(EnumValue), Mode=OneTime}" />
|
||||
<TextBlock Grid.Column="1"
|
||||
Text="{x:Bind EnumName}" />
|
||||
</Grid>
|
||||
</DataTemplate>
|
||||
</AutoSuggestBox.ItemTemplate>
|
||||
</AutoSuggestBox>
|
||||
|
||||
<!-- Image (File) Icon -->
|
||||
<TextBox x:Uid="Profile_IconBox"
|
||||
Grid.Column="1"
|
||||
MaxWidth="Infinity"
|
||||
HorizontalAlignment="Stretch"
|
||||
FontFamily="Segoe UI, Segoe Fluent Icons, Segoe MDL2 Assets"
|
||||
IsSpellCheckEnabled="False"
|
||||
Style="{StaticResource TextBoxSettingStyle}"
|
||||
Text="{x:Bind Profile.IconPath, Mode=TwoWay}"
|
||||
Visibility="{x:Bind Profile.UsingImageIcon, Mode=OneWay}" />
|
||||
<Button x:Uid="Profile_IconBrowse"
|
||||
Grid.Column="2"
|
||||
Margin="0"
|
||||
VerticalAlignment="Top"
|
||||
Click="Icon_Click"
|
||||
Style="{StaticResource BrowseButtonStyle}"
|
||||
Visibility="{x:Bind Profile.UsingImageIcon, Mode=OneWay}" />
|
||||
|
||||
<!-- Emoji Icon -->
|
||||
<TextBox x:Uid="Profile_IconEmojiBox"
|
||||
Grid.Column="1"
|
||||
MaxWidth="Infinity"
|
||||
FontFamily="Segoe UI, Segoe Fluent Icons, Segoe MDL2 Assets"
|
||||
IsSpellCheckEnabled="False"
|
||||
Style="{StaticResource TextBoxSettingStyle}"
|
||||
Text="{x:Bind Profile.CurrentEmojiIcon, Mode=TwoWay}"
|
||||
Visibility="{x:Bind Profile.UsingEmojiIcon, Mode=OneWay}" />
|
||||
</Grid>
|
||||
<local:IconPicker CurrentIconPath="{x:Bind Profile.IconPath, Mode=TwoWay}"
|
||||
WindowRoot="{x:Bind WindowRoot, Mode=OneWay}" />
|
||||
</local:SettingContainer.Content>
|
||||
</local:SettingContainer>
|
||||
|
||||
|
||||
@ -1110,11 +1110,11 @@
|
||||
<value>Icon</value>
|
||||
<comment>Header for a control to determine what icon can be used to represent this profile. This is not necessarily a file path, but can be one.</comment>
|
||||
</data>
|
||||
<data name="Profile_IconBox.[using:Windows.UI.Xaml.Automation]AutomationProperties.Name" xml:space="preserve">
|
||||
<data name="IconPicker_ImagePathBox.[using:Windows.UI.Xaml.Automation]AutomationProperties.Name" xml:space="preserve">
|
||||
<value>Icon</value>
|
||||
<comment>Name for a control to determine what icon can be used to represent this profile. This is not necessarily a file path, but can be one.</comment>
|
||||
<comment>Name for a control to determine what icon can be used. This is not necessarily a file path, but can be one. It's usually used for images.</comment>
|
||||
</data>
|
||||
<data name="Profile_IconEmojiBox.[using:Windows.UI.Xaml.Automation]AutomationProperties.Name" xml:space="preserve">
|
||||
<data name="IconPicker_EmojiBox.[using:Windows.UI.Xaml.Automation]AutomationProperties.Name" xml:space="preserve">
|
||||
<value>Icon</value>
|
||||
<comment>Name for a control to determine what icon can be used to represent this profile.</comment>
|
||||
</data>
|
||||
@ -1122,7 +1122,7 @@
|
||||
<value>Emoji or image file location of the icon used in the profile.</value>
|
||||
<comment>A description for what the "icon" setting does. Presented near "Profile_Icon".</comment>
|
||||
</data>
|
||||
<data name="Profile_IconBrowse.Content" xml:space="preserve">
|
||||
<data name="IconPicker_IconBrowse.Content" xml:space="preserve">
|
||||
<value>Browse...</value>
|
||||
<comment>Button label that opens a file picker in a new window. The "..." is standard to mean it will open a new window.</comment>
|
||||
</data>
|
||||
@ -2318,31 +2318,31 @@
|
||||
<value>Use theme color</value>
|
||||
<comment>Label for a button directing the user to use the tab color defined in the terminal's current theme.</comment>
|
||||
</data>
|
||||
<data name="Profile_IconTypeNone" xml:space="preserve">
|
||||
<data name="IconPicker_IconTypeNone" xml:space="preserve">
|
||||
<value>None</value>
|
||||
<comment>An option to choose from for the "icon style" dropdown. When selected, there will be no icon for the profile.</comment>
|
||||
<comment>An option to choose from for the "icon style" dropdown. When selected, there will be no icon set.</comment>
|
||||
</data>
|
||||
<data name="Profile_IconTypeImage" xml:space="preserve">
|
||||
<data name="IconPicker_IconTypeImage" xml:space="preserve">
|
||||
<value>File</value>
|
||||
<comment>An option to choose from for the "icon style" dropdown. When selected, a custom image can set for the profile's icon.</comment>
|
||||
<comment>An option to choose from for the "icon style" dropdown. When selected, a custom image can set as the icon.</comment>
|
||||
</data>
|
||||
<data name="Profile_IconTypeEmoji" xml:space="preserve">
|
||||
<data name="IconPicker_IconTypeEmoji" xml:space="preserve">
|
||||
<value>Emoji</value>
|
||||
<comment>An option to choose from for the "icon style" dropdown. When selected, an emoji can be set for the profile's icon.</comment>
|
||||
<comment>An option to choose from for the "icon style" dropdown. When selected, an emoji can be set as the icon.</comment>
|
||||
</data>
|
||||
<data name="Profile_IconTypeFontIcon" xml:space="preserve">
|
||||
<data name="IconPicker_IconTypeFontIcon" xml:space="preserve">
|
||||
<value>Built-in Icon</value>
|
||||
<comment>An option to choose from for the "icon style" dropdown. When selected, the user can choose from several preselected options to set the profile's icon.</comment>
|
||||
<comment>An option to choose from for the "icon style" dropdown. When selected, the user can choose from several preselected options to set as the icon.</comment>
|
||||
</data>
|
||||
<data name="Profile_IconEmojiBox.PlaceholderText" xml:space="preserve">
|
||||
<data name="IconPicker_EmojiBox.PlaceholderText" xml:space="preserve">
|
||||
<value>Use "Win + period" to open the emoji picker</value>
|
||||
<comment>"Win + period" refers to the OS key binding to open the emoji picker.</comment>
|
||||
</data>
|
||||
<data name="Profile_IconType.[using:Windows.UI.Xaml.Automation]AutomationProperties.Name" xml:space="preserve">
|
||||
<data name="IconPicker_IconType.[using:Windows.UI.Xaml.Automation]AutomationProperties.Name" xml:space="preserve">
|
||||
<value>Icon type</value>
|
||||
<comment>Accessible name for a control allowing the user to select the type of icon they would like to use.</comment>
|
||||
</data>
|
||||
<data name="Profile_BuiltInIcon.[using:Windows.UI.Xaml.Automation]AutomationProperties.Name" xml:space="preserve">
|
||||
<data name="IconPicker_BuiltInIcon.[using:Windows.UI.Xaml.Automation]AutomationProperties.Name" xml:space="preserve">
|
||||
<value>Icon</value>
|
||||
<comment>Accessible name for a control allowing the user to select the icon from a list of built in icons.</comment>
|
||||
</data>
|
||||
@ -2446,6 +2446,14 @@
|
||||
<value>Folder Name</value>
|
||||
<comment>Header for a control that allows the user to modify the name of the current folder entry.</comment>
|
||||
</data>
|
||||
<data name="NewTabMenu_CurrentFolderIcon.Header" xml:space="preserve">
|
||||
<value>Folder Icon</value>
|
||||
<comment>Header for a control that allows the user to modify the icon of the current folder entry.</comment>
|
||||
</data>
|
||||
<data name="NewTabMenu_CurrentFolderIcon.[using:Windows.UI.Xaml.Automation]AutomationProperties.Name" xml:space="preserve">
|
||||
<value>Folder Icon</value>
|
||||
<comment>Name for a control to that allows the user to modify the icon of the current folder entry.</comment>
|
||||
</data>
|
||||
<data name="NewTabMenu_CurrentFolderInlining.Header" xml:space="preserve">
|
||||
<value>Allow inlining</value>
|
||||
<comment>Header for a control that allows the nested entries to be presented inline rather than with a folder.</comment>
|
||||
@ -2709,4 +2717,8 @@
|
||||
<value>No results for "{}"</value>
|
||||
<comment>{Locked="{}"} Displayed when no results were found for a given query. "{}" will be replaced with the query.</comment>
|
||||
</data>
|
||||
<data name="IconPicker_BuiltInIcon.PlaceholderText" xml:space="preserve">
|
||||
<value>Type to filter icons</value>
|
||||
<comment>Placeholder text for a text box to filter and select an icon.</comment>
|
||||
</data>
|
||||
</root>
|
||||
@ -10,14 +10,14 @@ Licensed under the MIT license.
|
||||
|
||||
struct
|
||||
__declspec(uuid("6068ee1b-1ea0-4804-993a-42ef0c58d867"))
|
||||
IMediaResourceContainer : public IUnknown
|
||||
IMediaResourceContainer : public IUnknown
|
||||
{
|
||||
virtual void ResolveMediaResources(const winrt::Microsoft::Terminal::Settings::Model::MediaResourceResolver& resolver) = 0;
|
||||
};
|
||||
|
||||
struct
|
||||
__declspec(uuid("9f11361c-7c8f-45c9-8948-36b66d67eca8"))
|
||||
IPathlessMediaResourceContainer : public IUnknown
|
||||
IPathlessMediaResourceContainer : public IUnknown
|
||||
{
|
||||
virtual void ResolveMediaResourcesWithBasePath(const winrt::hstring& basePath, const winrt::Microsoft::Terminal::Settings::Model::MediaResourceResolver& resolver) = 0;
|
||||
};
|
||||
|
||||
@ -14,7 +14,7 @@ namespace ControlUnitTests
|
||||
public:
|
||||
MockConnection() noexcept = default;
|
||||
|
||||
void Initialize(const winrt::Windows::Foundation::Collections::ValueSet& /*settings*/){};
|
||||
void Initialize(const winrt::Windows::Foundation::Collections::ValueSet& /*settings*/) {};
|
||||
void Start() noexcept {};
|
||||
void WriteInput(const winrt::array_view<const char16_t> data)
|
||||
{
|
||||
|
||||
@ -47,11 +47,11 @@ public:
|
||||
#define _RTL_CONSTANT_STRING_remove_const_macro(s) \
|
||||
(const_cast<_RTL_CONSTANT_STRING_remove_const_template_class<sizeof((s)[0])>::T*>(s))
|
||||
|
||||
#define RTL_CONSTANT_STRING(s) \
|
||||
{ \
|
||||
sizeof(s) - sizeof((s)[0]), \
|
||||
sizeof(s) / sizeof(_RTL_CONSTANT_STRING_type_check(s)), \
|
||||
_RTL_CONSTANT_STRING_remove_const_macro(s) \
|
||||
#define RTL_CONSTANT_STRING(s) \
|
||||
{ \
|
||||
sizeof(s) - sizeof((s)[0]), \
|
||||
sizeof(s) / sizeof(_RTL_CONSTANT_STRING_type_check(s)), \
|
||||
_RTL_CONSTANT_STRING_remove_const_macro(s) \
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@ -31,7 +31,7 @@ Author(s):
|
||||
using namespace Microsoft::WRL;
|
||||
|
||||
struct __declspec(uuid(__CLSID_CConsoleHandoff))
|
||||
CConsoleHandoff : public RuntimeClass<RuntimeClassFlags<ClassicCom>, IConsoleHandoff, IDefaultTerminalMarker>
|
||||
CConsoleHandoff : public RuntimeClass<RuntimeClassFlags<ClassicCom>, IConsoleHandoff, IDefaultTerminalMarker>
|
||||
{
|
||||
#pragma region IConsoleHandoff
|
||||
STDMETHODIMP EstablishHandoff(HANDLE server,
|
||||
|
||||
@ -58,7 +58,7 @@ namespace
|
||||
|
||||
if (hNtDll != nullptr)
|
||||
{
|
||||
typedef NTSTATUS (*PfnNtOpenProcess)(HANDLE ProcessHandle, ACCESS_MASK DesiredAccess, POBJECT_ATTRIBUTES ObjectAttributes, CLIENT_ID * ClientId);
|
||||
typedef NTSTATUS (*PfnNtOpenProcess)(HANDLE ProcessHandle, ACCESS_MASK DesiredAccess, POBJECT_ATTRIBUTES ObjectAttributes, CLIENT_ID* ClientId);
|
||||
|
||||
static auto pfn = (PfnNtOpenProcess)GetProcAddress(hNtDll, "NtOpenProcess");
|
||||
|
||||
|
||||
@ -251,17 +251,17 @@ namespace til // Terminal Implementation Library. Also: "Today I Learned"
|
||||
rle_pair(rle_pair&&) = default;
|
||||
rle_pair& operator=(rle_pair&&) = default;
|
||||
|
||||
constexpr rle_pair(const T& value, const S& length) noexcept(std::is_nothrow_copy_constructible_v<T>&& std::is_nothrow_copy_constructible_v<S>) :
|
||||
constexpr rle_pair(const T& value, const S& length) noexcept(std::is_nothrow_copy_constructible_v<T> && std::is_nothrow_copy_constructible_v<S>) :
|
||||
value(value), length(length)
|
||||
{
|
||||
}
|
||||
|
||||
constexpr rle_pair(T&& value, S&& length) noexcept(std::is_nothrow_constructible_v<T>&& std::is_nothrow_constructible_v<S>) :
|
||||
constexpr rle_pair(T&& value, S&& length) noexcept(std::is_nothrow_constructible_v<T> && std::is_nothrow_constructible_v<S>) :
|
||||
value(std::forward<T>(value)), length(std::forward<S>(length))
|
||||
{
|
||||
}
|
||||
|
||||
constexpr void swap(rle_pair& other) noexcept(std::is_nothrow_swappable_v<T>&& std::is_nothrow_swappable_v<S>)
|
||||
constexpr void swap(rle_pair& other) noexcept(std::is_nothrow_swappable_v<T> && std::is_nothrow_swappable_v<S>)
|
||||
{
|
||||
if (this != std::addressof(other))
|
||||
{
|
||||
|
||||
@ -31,16 +31,16 @@ typedef enum DPI_AWARENESS
|
||||
DPI_AWARENESS_PER_MONITOR_AWARE = 2
|
||||
} DPI_AWARENESS;
|
||||
|
||||
#define DPI_AWARENESS_CONTEXT_UNAWARE ((DPI_AWARENESS_CONTEXT)-1)
|
||||
#define DPI_AWARENESS_CONTEXT_SYSTEM_AWARE ((DPI_AWARENESS_CONTEXT)-2)
|
||||
#define DPI_AWARENESS_CONTEXT_PER_MONITOR_AWARE ((DPI_AWARENESS_CONTEXT)-3)
|
||||
#define DPI_AWARENESS_CONTEXT_UNAWARE ((DPI_AWARENESS_CONTEXT) - 1)
|
||||
#define DPI_AWARENESS_CONTEXT_SYSTEM_AWARE ((DPI_AWARENESS_CONTEXT) - 2)
|
||||
#define DPI_AWARENESS_CONTEXT_PER_MONITOR_AWARE ((DPI_AWARENESS_CONTEXT) - 3)
|
||||
|
||||
#endif
|
||||
|
||||
// This type is being defined in RS2 but is percolating through the
|
||||
// tree. Def it here if it hasn't collided with our branch yet.
|
||||
#ifndef DPI_AWARENESS_CONTEXT_PER_MONITOR_AWARE_V2
|
||||
#define DPI_AWARENESS_CONTEXT_PER_MONITOR_AWARE_V2 ((DPI_AWARENESS_CONTEXT)-4)
|
||||
#define DPI_AWARENESS_CONTEXT_PER_MONITOR_AWARE_V2 ((DPI_AWARENESS_CONTEXT) - 4)
|
||||
#endif
|
||||
|
||||
namespace Microsoft::Console::Interactivity::Win32
|
||||
|
||||
@ -175,7 +175,7 @@ void Undo(HWND hControlWindow);
|
||||
//
|
||||
// Macros
|
||||
//
|
||||
#define AttrToRGB(Attr) (gpStateInfo->ColorTable[(Attr)&0x0F])
|
||||
#define AttrToRGB(Attr) (gpStateInfo->ColorTable[(Attr) & 0x0F])
|
||||
#define ScreenTextColor(pStateInfo) \
|
||||
(AttrToRGB(LOBYTE(pStateInfo->ScreenAttributes) & 0x0F))
|
||||
#define ScreenBkColor(pStateInfo) \
|
||||
|
||||
@ -72,7 +72,7 @@ typedef struct tagFACENODE
|
||||
|
||||
#pragma warning(pop)
|
||||
|
||||
#define TM_IS_TT_FONT(x) (((x)&TMPF_TRUETYPE) == TMPF_TRUETYPE)
|
||||
#define TM_IS_TT_FONT(x) (((x) & TMPF_TRUETYPE) == TMPF_TRUETYPE)
|
||||
#define IS_BOLD(w) ((w) >= FW_SEMIBOLD)
|
||||
#define SIZE_EQUAL(s1, s2) (((s1).X == (s2).X) && ((s1).Y == (s2).Y))
|
||||
#define POINTS_PER_INCH 72
|
||||
|
||||
@ -52,7 +52,7 @@ Revision History:
|
||||
SendMessage(hWnd, bLB ? LB_GETTEXT : CB_GETLBTEXT, w, 0L)
|
||||
|
||||
#define lcbFINDSTRINGEXACT(hWnd, bLB, pwsz) \
|
||||
(LONG) SendMessage(hWnd, bLB ? LB_FINDSTRINGEXACT : CB_FINDSTRINGEXACT, (WPARAM)-1, (LPARAM)pwsz)
|
||||
(LONG) SendMessage(hWnd, bLB ? LB_FINDSTRINGEXACT : CB_FINDSTRINGEXACT, (WPARAM) - 1, (LPARAM)pwsz)
|
||||
|
||||
#define lcbADDSTRING(hWnd, bLB, pwsz) \
|
||||
(LONG) SendMessage(hWnd, bLB ? LB_ADDSTRING : CB_ADDSTRING, 0, (LPARAM)pwsz)
|
||||
|
||||
@ -678,12 +678,12 @@ void BackendD3D::_debugUpdateShaders(const RenderingPayload& p) noexcept
|
||||
struct FileVS
|
||||
{
|
||||
std::wstring_view filename;
|
||||
wil::com_ptr<ID3D11VertexShader> BackendD3D::*target;
|
||||
wil::com_ptr<ID3D11VertexShader> BackendD3D::* target;
|
||||
};
|
||||
struct FilePS
|
||||
{
|
||||
std::wstring_view filename;
|
||||
wil::com_ptr<ID3D11PixelShader> BackendD3D::*target;
|
||||
wil::com_ptr<ID3D11PixelShader> BackendD3D::* target;
|
||||
};
|
||||
|
||||
static constexpr std::array filesVS{
|
||||
|
||||
@ -176,9 +176,9 @@ public:
|
||||
void RequestPresentationStateReport(const DispatchTypes::PresentationReportFormat /*format*/) override {} // DECRQPSR
|
||||
StringHandler RestorePresentationState(const DispatchTypes::PresentationReportFormat /*format*/) override { return nullptr; } // DECRSPS
|
||||
|
||||
void PlaySounds(const VTParameters /*parameters*/) override{}; // DECPS
|
||||
void PlaySounds(const VTParameters /*parameters*/) override {}; // DECPS
|
||||
|
||||
void SetOptionalFeatures(const til::enumset<OptionalFeature> /*features*/) override{};
|
||||
void SetOptionalFeatures(const til::enumset<OptionalFeature> /*features*/) override {};
|
||||
};
|
||||
|
||||
#pragma warning(default : 26440) // Restore "can be declared noexcept" warning
|
||||
|
||||
@ -316,7 +316,7 @@ namespace fuzz
|
||||
protected:
|
||||
CFuzzBase() :
|
||||
m_fFuzzed(FALSE),
|
||||
m_iPercentageTotal(100){};
|
||||
m_iPercentageTotal(100) {};
|
||||
virtual ~CFuzzBase() = default;
|
||||
|
||||
// Converts a percentage into a valid range. Note that riTotal
|
||||
|
||||
@ -404,8 +404,8 @@ namespace fuzz
|
||||
}
|
||||
|
||||
private:
|
||||
CFuzzLogic(){};
|
||||
virtual ~CFuzzLogic(){};
|
||||
CFuzzLogic() {};
|
||||
virtual ~CFuzzLogic() {};
|
||||
|
||||
static LPWSTR FuzzStringW_NoRealloc(__inout LPWSTR pwsz, __inout size_t& rcch)
|
||||
{
|
||||
|
||||
@ -416,28 +416,19 @@ function Invoke-CodeFormat() {
|
||||
[switch]$IgnoreXaml
|
||||
)
|
||||
|
||||
$clangFormatPath = & 'C:\Program Files (x86)\Microsoft Visual Studio\Installer\vswhere.exe' -latest -find "**\x64\bin\clang-format.exe"
|
||||
If ([String]::IsNullOrEmpty($clangFormatPath)) {
|
||||
Write-Error "No Visual Studio-supplied version of clang-format could be found."
|
||||
}
|
||||
|
||||
$root = Find-OpenConsoleRoot
|
||||
& "$root\dep\nuget\nuget.exe" restore "$root\tools\packages.config"
|
||||
$clangPackage = ([xml](Get-Content "$root\tools\packages.config")).packages.package | Where-Object id -like "clang-format*"
|
||||
$clangFormatPath = "$root\packages\$($clangPackage.id).$($clangPackage.version)\tools\clang-format.exe"
|
||||
Get-ChildItem -Recurse "$root\src" -Include *.cpp, *.hpp, *.h |
|
||||
Where FullName -NotLike "*Generated Files*" |
|
||||
Invoke-ClangFormat -ClangFormatPath $clangFormatPath
|
||||
|
||||
if ($IgnoreXaml) {
|
||||
# do nothing
|
||||
}
|
||||
else {
|
||||
if (-Not $IgnoreXaml) {
|
||||
Invoke-XamlFormat
|
||||
}
|
||||
}
|
||||
|
||||
#.SYNOPSIS
|
||||
# Download clang-format.exe required for code formatting
|
||||
function Get-Format()
|
||||
{
|
||||
$root = Find-OpenConsoleRoot
|
||||
& "$root\dep\nuget\nuget.exe" restore "$root\tools\packages.config"
|
||||
}
|
||||
|
||||
Export-ModuleMember -Function Set-MsbuildDevEnvironment,Invoke-OpenConsoleTests,Invoke-OpenConsoleBuild,Start-OpenConsole,Debug-OpenConsole,Invoke-CodeFormat,Invoke-XamlFormat,Test-XamlFormat,Get-Format
|
||||
Export-ModuleMember -Function Set-MsbuildDevEnvironment,Invoke-OpenConsoleTests,Invoke-OpenConsoleBuild,Start-OpenConsole,Debug-OpenConsole,Invoke-CodeFormat,Invoke-XamlFormat,Test-XamlFormat
|
||||
|
||||
@ -1,4 +0,0 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<packages>
|
||||
<package id="clang-format.win-x86" version="15.0.7" targetFramework="native" />
|
||||
</packages>
|
||||
Loading…
x
Reference in New Issue
Block a user