mirror of
https://github.com/microsoft/terminal.git
synced 2026-02-03 18:17:40 -06:00
Add IconPicker to New Tab Menu folders in SUI (#19591)
## Summary of the Pull Request This PR pulls out the icon picker used in Profiles_Base.xaml to be its own control. Then it's reused as a way to set an icon on folders in the new tab menu. As a part of pulling out the icon picker into its own control, some minor code-health polish was added (i.e. lazy loading icon types and built in icons). The new tab menu didn't have a `NavigateToPageArgs`, so I took the declaration from #19519 and moved it here. I chose to do that instead of creating a `NavigateToNewTabMenuArgs` since that's more strict and it would be removed as a part of #19519 anyways. Aside from that, the PR is pretty straightforward. ## References and Relevant Issues Part of #18281 ## Validation Steps Performed - Profile icon picker - [x] set none - [x] set built-in icon - [x] set emoji - [x] set file - [x] loads icons properly (for all of the scenarios above) - New tab menu folder icon picker - [x] set none - [x] set built-in icon - [x] set emoji - [x] set file - [x] loads icons properly (for all of the scenarios above)
This commit is contained in:
parent
cdf4bd9209
commit
a449899789
330
src/cascadia/TerminalSettingsEditor/IconPicker.cpp
Normal file
330
src/cascadia/TerminalSettingsEditor/IconPicker.cpp
Normal file
@ -0,0 +1,330 @@
|
|||||||
|
// 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 };
|
||||||
|
DependencyProperty IconPicker::_WindowRootProperty{ 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 } });
|
||||||
|
}
|
||||||
|
if (!_WindowRootProperty)
|
||||||
|
{
|
||||||
|
_WindowRootProperty =
|
||||||
|
DependencyProperty::Register(
|
||||||
|
L"WindowRoot",
|
||||||
|
xaml_typename<IHostedInWindow>(),
|
||||||
|
xaml_typename<Editor::IconPicker>(),
|
||||||
|
PropertyMetadata{ nullptr });
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
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));
|
||||||
|
}
|
||||||
|
}
|
||||||
65
src/cascadia/TerminalSettingsEditor/IconPicker.h
Normal file
65
src/cascadia/TerminalSettingsEditor/IconPicker.h
Normal file
@ -0,0 +1,65 @@
|
|||||||
|
// 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);
|
||||||
|
|
||||||
|
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);
|
||||||
|
DEPENDENCY_PROPERTY(IHostedInWindow, WindowRoot);
|
||||||
|
|
||||||
|
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;
|
||||||
|
|
||||||
|
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);
|
||||||
|
}
|
||||||
42
src/cascadia/TerminalSettingsEditor/IconPicker.idl
Normal file
42
src/cascadia/TerminalSettingsEditor/IconPicker.idl
Normal file
@ -0,0 +1,42 @@
|
|||||||
|
// 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;
|
||||||
|
static Windows.UI.Xaml.DependencyProperty WindowRootProperty { get; };
|
||||||
|
}
|
||||||
|
}
|
||||||
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>
|
||||||
@ -83,7 +83,7 @@ namespace winrt::Microsoft::Terminal::Settings::Editor::implementation
|
|||||||
const auto crumb = winrt::make<Breadcrumb>(box_value(newTabMenuTag), RS_(L"Nav_NewTabMenu/Content"), BreadcrumbSubPage::None);
|
const auto crumb = winrt::make<Breadcrumb>(box_value(newTabMenuTag), RS_(L"Nav_NewTabMenu/Content"), BreadcrumbSubPage::None);
|
||||||
_breadcrumbs.Append(crumb);
|
_breadcrumbs.Append(crumb);
|
||||||
}
|
}
|
||||||
contentFrame().Navigate(xaml_typename<Editor::NewTabMenu>(), _newTabMenuPageVM);
|
contentFrame().Navigate(xaml_typename<Editor::NewTabMenu>(), winrt::make<NavigateToPageArgs>(_newTabMenuPageVM, *this));
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
@ -538,7 +538,7 @@ namespace winrt::Microsoft::Terminal::Settings::Editor::implementation
|
|||||||
else
|
else
|
||||||
{
|
{
|
||||||
// Navigate to the NewTabMenu page
|
// Navigate to the NewTabMenu page
|
||||||
contentFrame().Navigate(xaml_typename<Editor::NewTabMenu>(), _newTabMenuPageVM);
|
contentFrame().Navigate(xaml_typename<Editor::NewTabMenu>(), winrt::make<NavigateToPageArgs>(_newTabMenuPageVM, *this));
|
||||||
const auto crumb = winrt::make<Breadcrumb>(box_value(clickedItemTag), RS_(L"Nav_NewTabMenu/Content"), BreadcrumbSubPage::None);
|
const auto crumb = winrt::make<Breadcrumb>(box_value(clickedItemTag), RS_(L"Nav_NewTabMenu/Content"), BreadcrumbSubPage::None);
|
||||||
_breadcrumbs.Append(crumb);
|
_breadcrumbs.Append(crumb);
|
||||||
}
|
}
|
||||||
@ -659,7 +659,7 @@ namespace winrt::Microsoft::Terminal::Settings::Editor::implementation
|
|||||||
{
|
{
|
||||||
_PreNavigateHelper();
|
_PreNavigateHelper();
|
||||||
|
|
||||||
contentFrame().Navigate(xaml_typename<Editor::NewTabMenu>(), _newTabMenuPageVM);
|
contentFrame().Navigate(xaml_typename<Editor::NewTabMenu>(), winrt::make<NavigateToPageArgs>(_newTabMenuPageVM, *this));
|
||||||
const auto crumb = winrt::make<Breadcrumb>(box_value(newTabMenuTag), RS_(L"Nav_NewTabMenu/Content"), BreadcrumbSubPage::None);
|
const auto crumb = winrt::make<Breadcrumb>(box_value(newTabMenuTag), RS_(L"Nav_NewTabMenu/Content"), BreadcrumbSubPage::None);
|
||||||
_breadcrumbs.Append(crumb);
|
_breadcrumbs.Append(crumb);
|
||||||
|
|
||||||
|
|||||||
@ -5,6 +5,7 @@
|
|||||||
|
|
||||||
#include "MainPage.g.h"
|
#include "MainPage.g.h"
|
||||||
#include "Breadcrumb.g.h"
|
#include "Breadcrumb.g.h"
|
||||||
|
#include "NavigateToPageArgs.g.h"
|
||||||
#include "Utils.h"
|
#include "Utils.h"
|
||||||
|
|
||||||
namespace winrt::Microsoft::Terminal::Settings::Editor::implementation
|
namespace winrt::Microsoft::Terminal::Settings::Editor::implementation
|
||||||
@ -23,6 +24,21 @@ namespace winrt::Microsoft::Terminal::Settings::Editor::implementation
|
|||||||
WINRT_PROPERTY(BreadcrumbSubPage, SubPage);
|
WINRT_PROPERTY(BreadcrumbSubPage, SubPage);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
struct NavigateToPageArgs : NavigateToPageArgsT<NavigateToPageArgs>
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
NavigateToPageArgs(Windows::Foundation::IInspectable viewModel, Editor::IHostedInWindow windowRoot) :
|
||||||
|
_ViewModel(viewModel),
|
||||||
|
_WindowRoot(windowRoot) {}
|
||||||
|
|
||||||
|
Editor::IHostedInWindow WindowRoot() const noexcept { return _WindowRoot; }
|
||||||
|
Windows::Foundation::IInspectable ViewModel() const noexcept { return _ViewModel; }
|
||||||
|
|
||||||
|
private:
|
||||||
|
Editor::IHostedInWindow _WindowRoot{ nullptr };
|
||||||
|
Windows::Foundation::IInspectable _ViewModel{ nullptr };
|
||||||
|
};
|
||||||
|
|
||||||
struct MainPage : MainPageT<MainPage>
|
struct MainPage : MainPageT<MainPage>
|
||||||
{
|
{
|
||||||
MainPage() = delete;
|
MainPage() = delete;
|
||||||
|
|||||||
@ -16,6 +16,14 @@ namespace Microsoft.Terminal.Settings.Editor
|
|||||||
UInt64 GetHostingWindow();
|
UInt64 GetHostingWindow();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// This is used to pass data between pages during navigation.
|
||||||
|
// All pages will migrate to using this in GH #19519.
|
||||||
|
runtimeclass NavigateToPageArgs
|
||||||
|
{
|
||||||
|
IHostedInWindow WindowRoot { get; };
|
||||||
|
IInspectable ViewModel { get; };
|
||||||
|
}
|
||||||
|
|
||||||
enum BreadcrumbSubPage
|
enum BreadcrumbSubPage
|
||||||
{
|
{
|
||||||
None = 0,
|
None = 0,
|
||||||
|
|||||||
@ -69,6 +69,10 @@
|
|||||||
<DependentUpon>NullableColorPicker.xaml</DependentUpon>
|
<DependentUpon>NullableColorPicker.xaml</DependentUpon>
|
||||||
<SubType>Code</SubType>
|
<SubType>Code</SubType>
|
||||||
</ClInclude>
|
</ClInclude>
|
||||||
|
<ClInclude Include="IconPicker.h">
|
||||||
|
<DependentUpon>IconPicker.xaml</DependentUpon>
|
||||||
|
<SubType>Code</SubType>
|
||||||
|
</ClInclude>
|
||||||
<ClInclude Include="EditColorScheme.h">
|
<ClInclude Include="EditColorScheme.h">
|
||||||
<DependentUpon>EditColorScheme.xaml</DependentUpon>
|
<DependentUpon>EditColorScheme.xaml</DependentUpon>
|
||||||
<SubType>Code</SubType>
|
<SubType>Code</SubType>
|
||||||
@ -193,6 +197,9 @@
|
|||||||
<Page Include="NullableColorPicker.xaml">
|
<Page Include="NullableColorPicker.xaml">
|
||||||
<SubType>Designer</SubType>
|
<SubType>Designer</SubType>
|
||||||
</Page>
|
</Page>
|
||||||
|
<Page Include="IconPicker.xaml">
|
||||||
|
<SubType>Designer</SubType>
|
||||||
|
</Page>
|
||||||
<Page Include="EditColorScheme.xaml">
|
<Page Include="EditColorScheme.xaml">
|
||||||
<SubType>Designer</SubType>
|
<SubType>Designer</SubType>
|
||||||
</Page>
|
</Page>
|
||||||
@ -269,6 +276,10 @@
|
|||||||
<DependentUpon>NullableColorPicker.xaml</DependentUpon>
|
<DependentUpon>NullableColorPicker.xaml</DependentUpon>
|
||||||
<SubType>Code</SubType>
|
<SubType>Code</SubType>
|
||||||
</ClCompile>
|
</ClCompile>
|
||||||
|
<ClCompile Include="IconPicker.cpp">
|
||||||
|
<DependentUpon>IconPicker.xaml</DependentUpon>
|
||||||
|
<SubType>Code</SubType>
|
||||||
|
</ClCompile>
|
||||||
<ClCompile Include="EditColorScheme.cpp">
|
<ClCompile Include="EditColorScheme.cpp">
|
||||||
<DependentUpon>EditColorScheme.xaml</DependentUpon>
|
<DependentUpon>EditColorScheme.xaml</DependentUpon>
|
||||||
<SubType>Code</SubType>
|
<SubType>Code</SubType>
|
||||||
@ -397,6 +408,10 @@
|
|||||||
<DependentUpon>NullableColorPicker.xaml</DependentUpon>
|
<DependentUpon>NullableColorPicker.xaml</DependentUpon>
|
||||||
<SubType>Code</SubType>
|
<SubType>Code</SubType>
|
||||||
</Midl>
|
</Midl>
|
||||||
|
<Midl Include="IconPicker.idl">
|
||||||
|
<DependentUpon>IconPicker.xaml</DependentUpon>
|
||||||
|
<SubType>Code</SubType>
|
||||||
|
</Midl>
|
||||||
<Midl Include="EditColorScheme.idl">
|
<Midl Include="EditColorScheme.idl">
|
||||||
<DependentUpon>EditColorScheme.xaml</DependentUpon>
|
<DependentUpon>EditColorScheme.xaml</DependentUpon>
|
||||||
<SubType>Code</SubType>
|
<SubType>Code</SubType>
|
||||||
|
|||||||
@ -55,6 +55,7 @@
|
|||||||
<Page Include="AddProfile.xaml" />
|
<Page Include="AddProfile.xaml" />
|
||||||
<Page Include="KeyChordListener.xaml" />
|
<Page Include="KeyChordListener.xaml" />
|
||||||
<Page Include="NullableColorPicker.xaml" />
|
<Page Include="NullableColorPicker.xaml" />
|
||||||
|
<Page Include="IconPicker.xaml" />
|
||||||
<Page Include="NewTabMenu.xaml" />
|
<Page Include="NewTabMenu.xaml" />
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
</Project>
|
</Project>
|
||||||
@ -4,6 +4,7 @@
|
|||||||
#include "pch.h"
|
#include "pch.h"
|
||||||
#include "NewTabMenu.h"
|
#include "NewTabMenu.h"
|
||||||
#include "NewTabMenu.g.cpp"
|
#include "NewTabMenu.g.cpp"
|
||||||
|
#include "NavigateToPageArgs.g.h"
|
||||||
#include "NewTabMenuEntryTemplateSelector.g.cpp"
|
#include "NewTabMenuEntryTemplateSelector.g.cpp"
|
||||||
#include "EnumEntry.h"
|
#include "EnumEntry.h"
|
||||||
|
|
||||||
@ -41,7 +42,9 @@ namespace winrt::Microsoft::Terminal::Settings::Editor::implementation
|
|||||||
|
|
||||||
void NewTabMenu::OnNavigatedTo(const NavigationEventArgs& e)
|
void NewTabMenu::OnNavigatedTo(const NavigationEventArgs& e)
|
||||||
{
|
{
|
||||||
_ViewModel = e.Parameter().as<Editor::NewTabMenuViewModel>();
|
const auto args = e.Parameter().as<Editor::NavigateToPageArgs>();
|
||||||
|
_ViewModel = args.ViewModel().as<Editor::NewTabMenuViewModel>();
|
||||||
|
_windowRoot = args.WindowRoot();
|
||||||
|
|
||||||
TraceLoggingWrite(
|
TraceLoggingWrite(
|
||||||
g_hTerminalSettingsEditorProvider,
|
g_hTerminalSettingsEditorProvider,
|
||||||
|
|||||||
@ -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_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);
|
void AddFolderNameTextBox_TextChanged(const winrt::Windows::Foundation::IInspectable& sender, const winrt::Windows::UI::Xaml::Controls::TextChangedEventArgs& e);
|
||||||
|
|
||||||
|
Editor::IHostedInWindow WindowRoot() const noexcept { return _windowRoot; }
|
||||||
WINRT_CALLBACK(PropertyChanged, Windows::UI::Xaml::Data::PropertyChangedEventHandler);
|
WINRT_CALLBACK(PropertyChanged, Windows::UI::Xaml::Data::PropertyChangedEventHandler);
|
||||||
WINRT_OBSERVABLE_PROPERTY(Editor::NewTabMenuViewModel, ViewModel, _PropertyChangedHandlers, nullptr);
|
WINRT_OBSERVABLE_PROPERTY(Editor::NewTabMenuViewModel, ViewModel, _PropertyChangedHandlers, nullptr);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
Editor::NewTabMenuEntryViewModel _draggedEntry{ nullptr };
|
Editor::NewTabMenuEntryViewModel _draggedEntry{ nullptr };
|
||||||
|
Editor::IHostedInWindow _windowRoot;
|
||||||
|
|
||||||
void _ScrollToEntry(const Editor::NewTabMenuEntryViewModel& entry);
|
void _ScrollToEntry(const Editor::NewTabMenuEntryViewModel& entry);
|
||||||
};
|
};
|
||||||
|
|||||||
@ -9,6 +9,7 @@ namespace Microsoft.Terminal.Settings.Editor
|
|||||||
{
|
{
|
||||||
NewTabMenu();
|
NewTabMenu();
|
||||||
NewTabMenuViewModel ViewModel { get; };
|
NewTabMenuViewModel ViewModel { get; };
|
||||||
|
IHostedInWindow WindowRoot { get; };
|
||||||
}
|
}
|
||||||
|
|
||||||
[default_interface] runtimeclass NewTabMenuEntryTemplateSelector : Windows.UI.Xaml.Controls.DataTemplateSelector
|
[default_interface] runtimeclass NewTabMenuEntryTemplateSelector : Windows.UI.Xaml.Controls.DataTemplateSelector
|
||||||
|
|||||||
@ -319,29 +319,48 @@
|
|||||||
Visibility="{x:Bind ViewModel.IsFolderView, Mode=OneWay}">
|
Visibility="{x:Bind ViewModel.IsFolderView, Mode=OneWay}">
|
||||||
<TextBlock x:Uid="NewTabMenu_CurrentFolderTextBlock"
|
<TextBlock x:Uid="NewTabMenu_CurrentFolderTextBlock"
|
||||||
Style="{StaticResource TextBlockSubHeaderStyle}" />
|
Style="{StaticResource TextBlockSubHeaderStyle}" />
|
||||||
|
|
||||||
<!-- TODO GH #18281: Icon -->
|
|
||||||
<!-- Once PR #17965 merges, we can add that kind of control to set an icon -->
|
|
||||||
|
|
||||||
<!-- Name -->
|
<!-- Name -->
|
||||||
<local:SettingContainer x:Uid="NewTabMenu_CurrentFolderName"
|
<local:SettingContainer x:Uid="NewTabMenu_CurrentFolderName"
|
||||||
Grid.Row="0"
|
|
||||||
CurrentValue="{x:Bind ViewModel.CurrentFolderName, Mode=OneWay}"
|
CurrentValue="{x:Bind ViewModel.CurrentFolderName, Mode=OneWay}"
|
||||||
Style="{StaticResource ExpanderSettingContainerStyle}">
|
Style="{StaticResource ExpanderSettingContainerStyle}">
|
||||||
<TextBox Style="{StaticResource TextBoxSettingStyle}"
|
<TextBox Style="{StaticResource TextBoxSettingStyle}"
|
||||||
Text="{x:Bind ViewModel.CurrentFolderName, Mode=TwoWay}" />
|
Text="{x:Bind ViewModel.CurrentFolderName, Mode=TwoWay}" />
|
||||||
</local:SettingContainer>
|
</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 -->
|
<!-- Inlining -->
|
||||||
<local:SettingContainer x:Uid="NewTabMenu_CurrentFolderInlining"
|
<local:SettingContainer x:Uid="NewTabMenu_CurrentFolderInlining">
|
||||||
Grid.Row="1">
|
|
||||||
<ToggleSwitch IsOn="{x:Bind ViewModel.CurrentFolderInlining, Mode=TwoWay}"
|
<ToggleSwitch IsOn="{x:Bind ViewModel.CurrentFolderInlining, Mode=TwoWay}"
|
||||||
Style="{StaticResource ToggleSwitchInExpanderStyle}" />
|
Style="{StaticResource ToggleSwitchInExpanderStyle}" />
|
||||||
</local:SettingContainer>
|
</local:SettingContainer>
|
||||||
|
|
||||||
<!-- Allow Empty -->
|
<!-- Allow Empty -->
|
||||||
<local:SettingContainer x:Uid="NewTabMenu_CurrentFolderAllowEmpty"
|
<local:SettingContainer x:Uid="NewTabMenu_CurrentFolderAllowEmpty">
|
||||||
Grid.Row="2">
|
|
||||||
<ToggleSwitch IsOn="{x:Bind ViewModel.CurrentFolderAllowEmpty, Mode=TwoWay}"
|
<ToggleSwitch IsOn="{x:Bind ViewModel.CurrentFolderAllowEmpty, Mode=TwoWay}"
|
||||||
Style="{StaticResource ToggleSwitchInExpanderStyle}" />
|
Style="{StaticResource ToggleSwitchInExpanderStyle}" />
|
||||||
</local:SettingContainer>
|
</local:SettingContainer>
|
||||||
|
|||||||
@ -3,6 +3,7 @@
|
|||||||
|
|
||||||
#include "pch.h"
|
#include "pch.h"
|
||||||
#include "NewTabMenuViewModel.h"
|
#include "NewTabMenuViewModel.h"
|
||||||
|
#include "IconPicker.h"
|
||||||
|
|
||||||
#include "NewTabMenuViewModel.g.cpp"
|
#include "NewTabMenuViewModel.g.cpp"
|
||||||
#include "FolderTreeViewEntry.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
|
// FolderTree needs to be updated when a folder is renamed
|
||||||
_folderTreeCache = nullptr;
|
_folderTreeCache = nullptr;
|
||||||
}
|
}
|
||||||
|
else if (viewModelProperty == L"Icon")
|
||||||
|
{
|
||||||
|
_NotifyChanges(L"CurrentFolderIconPreview", L"CurrentFolderLocalizedIcon", L"CurrentFolderIconPath", L"CurrentFolderUsingNoIcon");
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
hstring NewTabMenuViewModel::CurrentFolderName() const
|
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
|
Windows::Foundation::Collections::IObservableVector<Editor::NewTabMenuEntryViewModel> NewTabMenuViewModel::CurrentView() const
|
||||||
{
|
{
|
||||||
if (!_CurrentFolder)
|
if (!_CurrentFolder)
|
||||||
|
|||||||
@ -47,6 +47,12 @@ namespace winrt::Microsoft::Terminal::Settings::Editor::implementation
|
|||||||
bool CurrentFolderAllowEmpty() const;
|
bool CurrentFolderAllowEmpty() const;
|
||||||
void CurrentFolderAllowEmpty(bool value);
|
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<Model::Profile> AvailableProfiles() const { return _Settings.AllProfiles(); }
|
||||||
Windows::Foundation::Collections::IObservableVector<Editor::FolderTreeViewEntry> FolderTree() const;
|
Windows::Foundation::Collections::IObservableVector<Editor::FolderTreeViewEntry> FolderTree() const;
|
||||||
Windows::Foundation::Collections::IObservableVector<Editor::NewTabMenuEntryViewModel> CurrentView() const;
|
Windows::Foundation::Collections::IObservableVector<Editor::NewTabMenuEntryViewModel> CurrentView() const;
|
||||||
@ -134,6 +140,11 @@ namespace winrt::Microsoft::Terminal::Settings::Editor::implementation
|
|||||||
void Inlining(bool value);
|
void Inlining(bool value);
|
||||||
|
|
||||||
hstring Icon() const { return _FolderEntry.Icon().Path(); }
|
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, Name);
|
||||||
GETSET_OBSERVABLE_PROJECTED_SETTING(_FolderEntry, AllowEmpty);
|
GETSET_OBSERVABLE_PROJECTED_SETTING(_FolderEntry, AllowEmpty);
|
||||||
|
|||||||
@ -41,6 +41,11 @@ namespace Microsoft.Terminal.Settings.Editor
|
|||||||
String ProfileMatcherCommandline;
|
String ProfileMatcherCommandline;
|
||||||
String AddFolderName;
|
String AddFolderName;
|
||||||
|
|
||||||
|
Windows.UI.Xaml.Controls.IconElement CurrentFolderIconPreview { get; };
|
||||||
|
String CurrentFolderLocalizedIcon { get; };
|
||||||
|
String CurrentFolderIconPath;
|
||||||
|
Boolean CurrentFolderUsingNoIcon { get; };
|
||||||
|
|
||||||
void RequestReorderEntry(NewTabMenuEntryViewModel vm, Boolean goingUp);
|
void RequestReorderEntry(NewTabMenuEntryViewModel vm, Boolean goingUp);
|
||||||
void RequestDeleteEntry(NewTabMenuEntryViewModel vm);
|
void RequestDeleteEntry(NewTabMenuEntryViewModel vm);
|
||||||
void RequestMoveEntriesToFolder(IVector<NewTabMenuEntryViewModel> entries, FolderEntryViewModel folderEntry);
|
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);
|
FolderEntryViewModel(Microsoft.Terminal.Settings.Model.FolderEntry folderEntry, Microsoft.Terminal.Settings.Model.CascadiaSettings settings);
|
||||||
|
|
||||||
String Name;
|
String Name;
|
||||||
String Icon { get; };
|
String Icon;
|
||||||
Boolean Inlining;
|
Boolean Inlining;
|
||||||
Boolean AllowEmpty;
|
Boolean AllowEmpty;
|
||||||
IObservableVector<Microsoft.Terminal.Settings.Editor.NewTabMenuEntryViewModel> Entries;
|
IObservableVector<Microsoft.Terminal.Settings.Editor.NewTabMenuEntryViewModel> Entries;
|
||||||
|
|||||||
@ -4,14 +4,13 @@
|
|||||||
#include "pch.h"
|
#include "pch.h"
|
||||||
#include "ProfileViewModel.h"
|
#include "ProfileViewModel.h"
|
||||||
#include "ProfileViewModel.g.cpp"
|
#include "ProfileViewModel.g.cpp"
|
||||||
#include "EnumEntry.h"
|
|
||||||
#include "Appearances.h"
|
#include "Appearances.h"
|
||||||
|
#include "EnumEntry.h"
|
||||||
|
#include "IconPicker.h"
|
||||||
|
|
||||||
#include "../WinRTUtils/inc/Utils.h"
|
#include "../WinRTUtils/inc/Utils.h"
|
||||||
#include "../../renderer/base/FontCache.h"
|
#include "../../renderer/base/FontCache.h"
|
||||||
#include "../TerminalSettingsAppAdapterLib/TerminalSettings.h"
|
#include "../TerminalSettingsAppAdapterLib/TerminalSettings.h"
|
||||||
#include "SegoeFluentIconList.h"
|
|
||||||
#include "../../types/inc/utils.hpp"
|
|
||||||
|
|
||||||
using namespace winrt::Windows::UI::Text;
|
using namespace winrt::Windows::UI::Text;
|
||||||
using namespace winrt::Windows::UI::Xaml;
|
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::_MonospaceFontList{ nullptr };
|
||||||
Windows::Foundation::Collections::IObservableVector<Editor::Font> ProfileViewModel::_FontList{ 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) :
|
ProfileViewModel::ProfileViewModel(const Model::Profile& profile, const Model::CascadiaSettings& appSettings, const Windows::UI::Core::CoreDispatcher& dispatcher) :
|
||||||
_profile{ profile },
|
_profile{ profile },
|
||||||
@ -47,17 +43,6 @@ namespace winrt::Microsoft::Terminal::Settings::Editor::implementation
|
|||||||
|
|
||||||
_InitializeCurrentBellSounds();
|
_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.
|
// Add a property changed handler to our own property changed event.
|
||||||
// This propagates changes from the settings model to anybody listening to our
|
// This propagates changes from the settings model to anybody listening to our
|
||||||
// unique view model members.
|
// unique view model members.
|
||||||
@ -92,32 +77,15 @@ namespace winrt::Microsoft::Terminal::Settings::Editor::implementation
|
|||||||
}
|
}
|
||||||
else if (viewModelProperty == L"Icon")
|
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.
|
// The icon changed; let's re-evaluate it with its new context.
|
||||||
_appSettings.ResolveMediaResources();
|
_appSettings.ResolveMediaResources();
|
||||||
}
|
|
||||||
else if (viewModelProperty == L"CurrentIconType")
|
// Propagate the rendered icon into a preview (i.e. nav view, container item)
|
||||||
{
|
_NotifyChanges(L"LocalizedIcon",
|
||||||
// "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",
|
|
||||||
L"IconPreview",
|
L"IconPreview",
|
||||||
L"IconPath",
|
L"IconPath",
|
||||||
L"EvaluatedIcon");
|
L"EvaluatedIcon",
|
||||||
}
|
L"UsingNoIcon");
|
||||||
else if (viewModelProperty == L"CurrentBuiltInIcon")
|
|
||||||
{
|
|
||||||
IconPath(unbox_value<hstring>(_CurrentBuiltInIcon.EnumValue()));
|
|
||||||
}
|
|
||||||
else if (viewModelProperty == L"CurrentEmojiIcon")
|
|
||||||
{
|
|
||||||
IconPath(CurrentEmojiIcon());
|
|
||||||
}
|
}
|
||||||
else if (viewModelProperty == L"CurrentBellSounds")
|
else if (viewModelProperty == L"CurrentBellSounds")
|
||||||
{
|
{
|
||||||
@ -190,61 +158,6 @@ namespace winrt::Microsoft::Terminal::Settings::Editor::implementation
|
|||||||
_defaultAppearanceViewModel.IsDefault(true);
|
_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
|
void ProfileViewModel::LeftPadding(double value) noexcept
|
||||||
{
|
{
|
||||||
if (std::abs(_parsedPadding.Left - value) >= .0001)
|
if (std::abs(_parsedPadding.Left - value) >= .0001)
|
||||||
@ -636,9 +549,9 @@ namespace winrt::Microsoft::Terminal::Settings::Editor::implementation
|
|||||||
|
|
||||||
winrt::hstring ProfileViewModel::LocalizedIcon() const
|
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
|
return IconPath(); // For display as a string
|
||||||
}
|
}
|
||||||
@ -652,83 +565,10 @@ namespace winrt::Microsoft::Terminal::Settings::Editor::implementation
|
|||||||
return icon;
|
return icon;
|
||||||
}
|
}
|
||||||
|
|
||||||
void ProfileViewModel::CurrentIconType(const Windows::Foundation::IInspectable& value)
|
bool ProfileViewModel::UsingNoIcon() const noexcept
|
||||||
{
|
{
|
||||||
if (_currentIconType != value)
|
const auto iconPath{ IconPath() };
|
||||||
{
|
return iconPath.empty() || iconPath == IconPicker::HideIconValue;
|
||||||
// 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);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
hstring ProfileViewModel::BellStylePreview() const
|
hstring ProfileViewModel::BellStylePreview() const
|
||||||
|
|||||||
@ -49,7 +49,6 @@ namespace winrt::Microsoft::Terminal::Settings::Editor::implementation
|
|||||||
static void UpdateFontList() noexcept;
|
static void UpdateFontList() noexcept;
|
||||||
static Windows::Foundation::Collections::IObservableVector<Editor::Font> CompleteFontList() noexcept { return _FontList; };
|
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::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);
|
ProfileViewModel(const Model::Profile& profile, const Model::CascadiaSettings& settings, const Windows::UI::Core::CoreDispatcher& dispatcher);
|
||||||
Control::IControlSettings TermSettings() const;
|
Control::IControlSettings TermSettings() const;
|
||||||
@ -86,23 +85,15 @@ namespace winrt::Microsoft::Terminal::Settings::Editor::implementation
|
|||||||
{
|
{
|
||||||
return _profile.Icon().Resolved();
|
return _profile.Icon().Resolved();
|
||||||
}
|
}
|
||||||
Windows::Foundation::IInspectable CurrentIconType() const noexcept
|
|
||||||
{
|
|
||||||
return _currentIconType;
|
|
||||||
}
|
|
||||||
Windows::UI::Xaml::Controls::IconElement IconPreview() const;
|
Windows::UI::Xaml::Controls::IconElement IconPreview() const;
|
||||||
winrt::hstring LocalizedIcon() 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(); }
|
winrt::hstring IconPath() const { return _profile.Icon().Path(); }
|
||||||
void IconPath(const winrt::hstring& path)
|
void IconPath(const winrt::hstring& path)
|
||||||
{
|
{
|
||||||
Icon(Model::MediaResourceHelper::FromString(path));
|
Icon(Model::MediaResourceHelper::FromString(path));
|
||||||
_NotifyChanges(L"Icon", L"IconPath");
|
_NotifyChanges(L"Icon", L"IconPath");
|
||||||
}
|
}
|
||||||
|
bool UsingNoIcon() const noexcept;
|
||||||
|
|
||||||
// starting directory
|
// starting directory
|
||||||
hstring CurrentStartingDirectoryPreview() const;
|
hstring CurrentStartingDirectoryPreview() const;
|
||||||
@ -134,8 +125,6 @@ namespace winrt::Microsoft::Terminal::Settings::Editor::implementation
|
|||||||
|
|
||||||
VIEW_MODEL_OBSERVABLE_PROPERTY(ProfileSubPage, CurrentPage);
|
VIEW_MODEL_OBSERVABLE_PROPERTY(ProfileSubPage, CurrentPage);
|
||||||
VIEW_MODEL_OBSERVABLE_PROPERTY(Windows::Foundation::Collections::IObservableVector<Editor::BellSoundViewModel>, CurrentBellSounds);
|
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, Guid);
|
||||||
PERMANENT_OBSERVABLE_PROJECTED_SETTING(_profile, ConnectionType);
|
PERMANENT_OBSERVABLE_PROJECTED_SETTING(_profile, ConnectionType);
|
||||||
@ -174,7 +163,6 @@ namespace winrt::Microsoft::Terminal::Settings::Editor::implementation
|
|||||||
|
|
||||||
WINRT_PROPERTY(bool, IsBaseLayer, false);
|
WINRT_PROPERTY(bool, IsBaseLayer, false);
|
||||||
WINRT_PROPERTY(bool, FocusDeleteButton, false);
|
WINRT_PROPERTY(bool, FocusDeleteButton, false);
|
||||||
WINRT_PROPERTY(Windows::Foundation::Collections::IVector<Windows::Foundation::IInspectable>, IconTypes);
|
|
||||||
GETSET_BINDABLE_ENUM_SETTING(AntiAliasingMode, Microsoft::Terminal::Control::TextAntialiasingMode, AntialiasingMode);
|
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(CloseOnExitMode, Microsoft::Terminal::Settings::Model::CloseOnExitMode, CloseOnExit);
|
||||||
GETSET_BINDABLE_ENUM_SETTING(ScrollState, Microsoft::Terminal::Control::ScrollbarState, ScrollState);
|
GETSET_BINDABLE_ENUM_SETTING(ScrollState, Microsoft::Terminal::Control::ScrollbarState, ScrollState);
|
||||||
@ -185,8 +173,6 @@ namespace winrt::Microsoft::Terminal::Settings::Editor::implementation
|
|||||||
winrt::guid _originalProfileGuid{};
|
winrt::guid _originalProfileGuid{};
|
||||||
winrt::hstring _lastBgImagePath;
|
winrt::hstring _lastBgImagePath;
|
||||||
winrt::hstring _lastStartingDirectoryPath;
|
winrt::hstring _lastStartingDirectoryPath;
|
||||||
winrt::hstring _lastIconPath;
|
|
||||||
Windows::Foundation::IInspectable _currentIconType{};
|
|
||||||
Editor::AppearanceViewModel _defaultAppearanceViewModel;
|
Editor::AppearanceViewModel _defaultAppearanceViewModel;
|
||||||
Windows::UI::Core::CoreDispatcher _dispatcher;
|
Windows::UI::Core::CoreDispatcher _dispatcher;
|
||||||
|
|
||||||
@ -197,13 +183,9 @@ namespace winrt::Microsoft::Terminal::Settings::Editor::implementation
|
|||||||
void _MarkDuplicateBellSoundDirectories();
|
void _MarkDuplicateBellSoundDirectories();
|
||||||
static Windows::Foundation::Collections::IObservableVector<Editor::Font> _MonospaceFontList;
|
static Windows::Foundation::Collections::IObservableVector<Editor::Font> _MonospaceFontList;
|
||||||
static Windows::Foundation::Collections::IObservableVector<Editor::Font> _FontList;
|
static Windows::Foundation::Collections::IObservableVector<Editor::Font> _FontList;
|
||||||
static Windows::Foundation::Collections::IObservableVector<Editor::EnumEntry> _BuiltInIcons;
|
|
||||||
|
|
||||||
Model::CascadiaSettings _appSettings;
|
Model::CascadiaSettings _appSettings;
|
||||||
Editor::AppearanceViewModel _unfocusedAppearanceViewModel;
|
Editor::AppearanceViewModel _unfocusedAppearanceViewModel;
|
||||||
void _UpdateBuiltInIcons();
|
|
||||||
void _DeduceCurrentIconType();
|
|
||||||
void _DeduceCurrentBuiltInIcon();
|
|
||||||
};
|
};
|
||||||
|
|
||||||
struct DeleteProfileEventArgs :
|
struct DeleteProfileEventArgs :
|
||||||
|
|||||||
@ -42,14 +42,6 @@ namespace Microsoft.Terminal.Settings.Editor
|
|||||||
Advanced = 3
|
Advanced = 3
|
||||||
};
|
};
|
||||||
|
|
||||||
enum IconType
|
|
||||||
{
|
|
||||||
None = 0,
|
|
||||||
FontIcon,
|
|
||||||
Image,
|
|
||||||
Emoji
|
|
||||||
};
|
|
||||||
|
|
||||||
runtimeclass ProfileViewModel : Windows.UI.Xaml.Data.INotifyPropertyChanged
|
runtimeclass ProfileViewModel : Windows.UI.Xaml.Data.INotifyPropertyChanged
|
||||||
{
|
{
|
||||||
event Windows.Foundation.TypedEventHandler<ProfileViewModel, DeleteProfileEventArgs> DeleteProfileRequested;
|
event Windows.Foundation.TypedEventHandler<ProfileViewModel, DeleteProfileEventArgs> DeleteProfileRequested;
|
||||||
@ -107,17 +99,8 @@ namespace Microsoft.Terminal.Settings.Editor
|
|||||||
Windows.UI.Xaml.Controls.IconElement IconPreview { get; };
|
Windows.UI.Xaml.Controls.IconElement IconPreview { get; };
|
||||||
String EvaluatedIcon { get; };
|
String EvaluatedIcon { get; };
|
||||||
String LocalizedIcon { 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;
|
String IconPath;
|
||||||
|
Boolean UsingNoIcon { get; };
|
||||||
EnumEntry CurrentBuiltInIcon;
|
|
||||||
Windows.Foundation.Collections.IObservableVector<EnumEntry> BuiltInIcons { get; };
|
|
||||||
|
|
||||||
String TabTitlePreview { get; };
|
String TabTitlePreview { get; };
|
||||||
String AnswerbackMessagePreview { get; };
|
String AnswerbackMessagePreview { get; };
|
||||||
|
|||||||
@ -133,18 +133,6 @@ 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&)
|
safe_void_coroutine Profiles_Base::StartingDirectory_Click(const IInspectable&, const RoutedEventArgs&)
|
||||||
{
|
{
|
||||||
auto lifetime = get_strong();
|
auto lifetime = get_strong();
|
||||||
@ -169,77 +157,4 @@ namespace winrt::Microsoft::Terminal::Settings::Editor::implementation
|
|||||||
_Profile.StartingDirectory(folder);
|
_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);
|
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 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);
|
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 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 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 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);
|
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;
|
til::property_changed_event PropertyChanged;
|
||||||
|
Editor::IHostedInWindow WindowRoot() const noexcept { return _windowRoot; }
|
||||||
WINRT_PROPERTY(Editor::ProfileViewModel, Profile, nullptr);
|
WINRT_PROPERTY(Editor::ProfileViewModel, Profile, nullptr);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
Windows::UI::Xaml::Data::INotifyPropertyChanged::PropertyChanged_revoker _ViewModelChangedRevoker;
|
Windows::UI::Xaml::Data::INotifyPropertyChanged::PropertyChanged_revoker _ViewModelChangedRevoker;
|
||||||
winrt::Windows::UI::Xaml::Controls::SwapChainPanel::LayoutUpdated_revoker _layoutUpdatedRevoker;
|
winrt::Windows::UI::Xaml::Controls::SwapChainPanel::LayoutUpdated_revoker _layoutUpdatedRevoker;
|
||||||
Editor::IHostedInWindow _windowRoot;
|
Editor::IHostedInWindow _windowRoot;
|
||||||
Windows::Foundation::Collections::IObservableVector<Editor::EnumEntry> _filteredBuiltInIcons;
|
|
||||||
std::wstring _iconFilter;
|
|
||||||
|
|
||||||
void _updateIconFilter(std::wstring_view filter);
|
|
||||||
void _updateFilteredIconList();
|
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|||||||
@ -2,6 +2,7 @@
|
|||||||
// Licensed under the MIT license.
|
// Licensed under the MIT license.
|
||||||
|
|
||||||
import "ProfileViewModel.idl";
|
import "ProfileViewModel.idl";
|
||||||
|
import "MainPage.idl";
|
||||||
|
|
||||||
namespace Microsoft.Terminal.Settings.Editor
|
namespace Microsoft.Terminal.Settings.Editor
|
||||||
{
|
{
|
||||||
@ -9,8 +10,6 @@ namespace Microsoft.Terminal.Settings.Editor
|
|||||||
{
|
{
|
||||||
Profiles_Base();
|
Profiles_Base();
|
||||||
ProfileViewModel Profile { get; };
|
ProfileViewModel Profile { get; };
|
||||||
Windows.Foundation.Collections.IObservableVector<EnumEntry> FilteredBuiltInIconList { get; };
|
IHostedInWindow WindowRoot { get; };
|
||||||
|
|
||||||
static Windows.UI.Xaml.Controls.IconSource BuiltInIconConverter(IInspectable iconVal);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -122,82 +122,8 @@
|
|||||||
</Grid>
|
</Grid>
|
||||||
</local:SettingContainer.CurrentValue>
|
</local:SettingContainer.CurrentValue>
|
||||||
<local:SettingContainer.Content>
|
<local:SettingContainer.Content>
|
||||||
<Grid ColumnSpacing="12">
|
<local:IconPicker CurrentIconPath="{x:Bind Profile.IconPath, Mode=TwoWay}"
|
||||||
<Grid.ColumnDefinitions>
|
WindowRoot="{x:Bind WindowRoot, Mode=OneWay}" />
|
||||||
<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:SettingContainer.Content>
|
</local:SettingContainer.Content>
|
||||||
</local:SettingContainer>
|
</local:SettingContainer>
|
||||||
|
|
||||||
|
|||||||
@ -1110,11 +1110,11 @@
|
|||||||
<value>Icon</value>
|
<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>
|
<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>
|
||||||
<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>
|
<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>
|
||||||
<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>
|
<value>Icon</value>
|
||||||
<comment>Name for a control to determine what icon can be used to represent this profile.</comment>
|
<comment>Name for a control to determine what icon can be used to represent this profile.</comment>
|
||||||
</data>
|
</data>
|
||||||
@ -1122,7 +1122,7 @@
|
|||||||
<value>Emoji or image file location of the icon used in the profile.</value>
|
<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>
|
<comment>A description for what the "icon" setting does. Presented near "Profile_Icon".</comment>
|
||||||
</data>
|
</data>
|
||||||
<data name="Profile_IconBrowse.Content" xml:space="preserve">
|
<data name="IconPicker_IconBrowse.Content" xml:space="preserve">
|
||||||
<value>Browse...</value>
|
<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>
|
<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>
|
</data>
|
||||||
@ -2318,31 +2318,31 @@
|
|||||||
<value>Use theme color</value>
|
<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>
|
<comment>Label for a button directing the user to use the tab color defined in the terminal's current theme.</comment>
|
||||||
</data>
|
</data>
|
||||||
<data name="Profile_IconTypeNone" xml:space="preserve">
|
<data name="IconPicker_IconTypeNone" xml:space="preserve">
|
||||||
<value>None</value>
|
<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>
|
||||||
<data name="Profile_IconTypeImage" xml:space="preserve">
|
<data name="IconPicker_IconTypeImage" xml:space="preserve">
|
||||||
<value>File</value>
|
<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>
|
||||||
<data name="Profile_IconTypeEmoji" xml:space="preserve">
|
<data name="IconPicker_IconTypeEmoji" xml:space="preserve">
|
||||||
<value>Emoji</value>
|
<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>
|
||||||
<data name="Profile_IconTypeFontIcon" xml:space="preserve">
|
<data name="IconPicker_IconTypeFontIcon" xml:space="preserve">
|
||||||
<value>Built-in Icon</value>
|
<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>
|
||||||
<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>
|
<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>
|
<comment>"Win + period" refers to the OS key binding to open the emoji picker.</comment>
|
||||||
</data>
|
</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>
|
<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>
|
<comment>Accessible name for a control allowing the user to select the type of icon they would like to use.</comment>
|
||||||
</data>
|
</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>
|
<value>Icon</value>
|
||||||
<comment>Accessible name for a control allowing the user to select the icon from a list of built in icons.</comment>
|
<comment>Accessible name for a control allowing the user to select the icon from a list of built in icons.</comment>
|
||||||
</data>
|
</data>
|
||||||
@ -2446,6 +2446,14 @@
|
|||||||
<value>Folder Name</value>
|
<value>Folder Name</value>
|
||||||
<comment>Header for a control that allows the user to modify the name of the current folder entry.</comment>
|
<comment>Header for a control that allows the user to modify the name of the current folder entry.</comment>
|
||||||
</data>
|
</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">
|
<data name="NewTabMenu_CurrentFolderInlining.Header" xml:space="preserve">
|
||||||
<value>Allow inlining</value>
|
<value>Allow inlining</value>
|
||||||
<comment>Header for a control that allows the nested entries to be presented inline rather than with a folder.</comment>
|
<comment>Header for a control that allows the nested entries to be presented inline rather than with a folder.</comment>
|
||||||
@ -2701,4 +2709,8 @@
|
|||||||
<data name="Settings_ResetApplicationStateConfirmationButton.Content" xml:space="preserve">
|
<data name="Settings_ResetApplicationStateConfirmationButton.Content" xml:space="preserve">
|
||||||
<value>Yes, clear the cache</value>
|
<value>Yes, clear the cache</value>
|
||||||
</data>
|
</data>
|
||||||
</root>
|
<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>
|
||||||
Loading…
x
Reference in New Issue
Block a user