Skip to content

Commit

Permalink
Fix revert button for Icon
Browse files Browse the repository at this point in the history
  • Loading branch information
carlos-zamora committed Nov 20, 2024
1 parent 9df6b03 commit e46ed40
Show file tree
Hide file tree
Showing 5 changed files with 115 additions and 46 deletions.
4 changes: 2 additions & 2 deletions src/cascadia/TerminalSettingsEditor/MainPage.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -634,9 +634,9 @@ namespace winrt::Microsoft::Terminal::Settings::Editor::implementation
if (auto menuItem{ weakMenuItem.get() })
{
const auto& tag{ menuItem.Tag().as<Editor::ProfileViewModel>() };
if (args.PropertyName() == L"Icon")

This comment has been minimized.

Copy link
@DHowett

DHowett Nov 20, 2024

Member

Can you move this whole commit to a separate PR?

if (args.PropertyName() == L"Icon" || args.PropertyName() == L"EvaluatedIcon")
{
menuItem.Icon(UI::IconPathConverter::IconWUX(tag.Icon()));
menuItem.Icon(UI::IconPathConverter::IconWUX(tag.EvaluatedIcon()));
}
else if (args.PropertyName() == L"Name")
{
Expand Down
61 changes: 37 additions & 24 deletions src/cascadia/TerminalSettingsEditor/ProfileViewModel.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -43,12 +43,15 @@ namespace winrt::Microsoft::Terminal::Settings::Editor::implementation
INITIALIZE_BINDABLE_ENUM_SETTING(ScrollState, ScrollbarState, winrt::Microsoft::Terminal::Control::ScrollbarState, L"Profile_ScrollbarVisibility", L"Content");

// set up IconTypes
_IconTypes = winrt::single_threaded_vector<IInspectable>();
_IconTypes.Append(make<EnumEntry>(RS_(L"Profile_IconTypeNone"), box_value(IconType::None)));
_IconTypes.Append(make<EnumEntry>(RS_(L"Profile_IconTypeFontIcon"), box_value(IconType::FontIcon)));
_IconTypes.Append(make<EnumEntry>(RS_(L"Profile_IconTypeEmoji"), box_value(IconType::Emoji)));
_IconTypes.Append(make<EnumEntry>(RS_(L"Profile_IconTypeImage"), box_value(IconType::Image)));
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
Expand Down Expand Up @@ -84,12 +87,21 @@ 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();
_NotifyChanges(L"LocalizedIcon", L"EvaluatedIcon", L"IconPreview");
}
else if (viewModelProperty == L"CurrentIconType")
{
_NotifyChanges(L"UsingNoIcon", L"UsingBuiltInIcon", L"UsingEmojiIcon", L"UsingImageIcon");
// "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"EvaluatedIcon");
}
else if (viewModelProperty == L"CurrentBuiltInIcon")
{
Expand All @@ -113,12 +125,6 @@ namespace winrt::Microsoft::Terminal::Settings::Editor::implementation
UpdateFontList();
}

if (!_BuiltInIcons)
{
_UpdateBuiltInIcons();
}
_DeduceCurrentBuiltInIcon();

if (profile.HasUnfocusedAppearance())
{
_unfocusedAppearanceViewModel = winrt::make<implementation::AppearanceViewModel>(profile.UnfocusedAppearance().try_as<AppearanceConfig>());
Expand All @@ -129,35 +135,37 @@ namespace winrt::Microsoft::Terminal::Settings::Editor::implementation

void ProfileViewModel::_UpdateBuiltInIcons()
{
_BuiltInIcons = single_threaded_vector<IInspectable>();
std::vector<IInspectable> builtInIcons;
for (auto& [val, name] : s_SegoeFluentIcons)
{
_BuiltInIcons.Append(make<EnumEntry>(hstring{ name }, box_value(val)));
builtInIcons.emplace_back(make<EnumEntry>(hstring{ name }, box_value(val)));
}
_BuiltInIcons = single_threaded_vector<IInspectable>(std::move(builtInIcons));
}

void ProfileViewModel::_DeduceCurrentIconType()
{
const auto& profileIcon = _profile.Icon();
if (profileIcon == HideIconValue)
{
CurrentIconType(_IconTypes.GetAt(0));
_currentIconType = _IconTypes.GetAt(0);
}
else if (L"\uE700" <= profileIcon && profileIcon <= L"\uF8B3")
{
CurrentIconType(_IconTypes.GetAt(1));
_currentIconType = _IconTypes.GetAt(1);
_DeduceCurrentBuiltInIcon();
}
else if (profileIcon.size() <= 2)
{
// 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));
_currentIconType = _IconTypes.GetAt(2);
}
else
{
CurrentIconType(_IconTypes.GetAt(3));
_currentIconType = _IconTypes.GetAt(3);
}
_NotifyChanges(L"CurrentIconType");
}

void ProfileViewModel::_DeduceCurrentBuiltInIcon()
Expand All @@ -177,6 +185,7 @@ namespace winrt::Microsoft::Terminal::Settings::Editor::implementation
}
}
_CurrentBuiltInIcon = _BuiltInIcons.GetAt(0);
_NotifyChanges(L"CurrentBuiltInIcon");
}

Model::TerminalSettings ProfileViewModel::TermSettings() const
Expand Down Expand Up @@ -452,7 +461,7 @@ namespace winrt::Microsoft::Terminal::Settings::Editor::implementation
{
case IconType::None:
{
Icon(HideIconValue);
_profile.Icon(HideIconValue);
break;
}
case IconType::Image:
Expand All @@ -461,26 +470,30 @@ namespace winrt::Microsoft::Terminal::Settings::Editor::implementation
{
// Conversely, if we switch to Image,
// retrieve that saved value and apply it
Icon(_lastIconPath);
_profile.Icon(_lastIconPath);
}
break;
}
case IconType::FontIcon:
{
if (_CurrentBuiltInIcon)
{
Icon(unbox_value<hstring>(_CurrentBuiltInIcon.as<Editor::EnumEntry>().EnumValue()));
_profile.Icon(unbox_value<hstring>(_CurrentBuiltInIcon.as<Editor::EnumEntry>().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({});
}
}
_NotifyChanges(L"CurrentIconType");
// We're not using the VM's Icon() setter above,
// so notify HasIcon changed manually
_NotifyChanges(L"CurrentIconType", L"HasIcon");
}
};
}

bool ProfileViewModel::UsingNoIcon() const
{
Expand Down
33 changes: 15 additions & 18 deletions src/cascadia/TerminalSettingsEditor/Profiles_Base.xaml
Original file line number Diff line number Diff line change
Expand Up @@ -102,27 +102,24 @@
<!-- Icon -->
<local:SettingContainer x:Uid="Profile_Icon"
ClearSettingValue="{x:Bind Profile.ClearIcon}"
CurrentValue="{x:Bind Profile, Mode=OneWay}"
HasSettingValue="{x:Bind Profile.HasIcon, Mode=OneWay}"
SettingOverrideSource="{x:Bind Profile.IconOverrideSource, Mode=OneWay}"
Style="{StaticResource ExpanderSettingContainerStyleWithComplexPreview}">
<local:SettingContainer.CurrentValueTemplate>
<DataTemplate x:DataType="local:ProfileViewModel">
<Grid>
<ContentControl Width="16"
Height="16"
Content="{x:Bind IconPreview, Mode=OneWay}"
Visibility="{x:Bind mtu:Converters.InvertedBooleanToVisibility(UsingNoIcon), 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 LocalizedIcon, Mode=OneWay}"
Visibility="{x:Bind UsingNoIcon, Mode=OneWay}" />
</Grid>
</DataTemplate>
</local:SettingContainer.CurrentValueTemplate>
<local:SettingContainer.CurrentValue>
<Grid>
<ContentControl Width="16"
Height="16"
Content="{x:Bind Profile.IconPreview, Mode=OneWay}"
Visibility="{x:Bind mtu:Converters.InvertedBooleanToVisibility(Profile.UsingNoIcon), 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 Profile.LocalizedIcon, Mode=OneWay}"
Visibility="{x:Bind Profile.UsingNoIcon, Mode=OneWay}" />
</Grid>
</local:SettingContainer.CurrentValue>
<local:SettingContainer.Content>
<Grid ColumnSpacing="10">
<Grid.ColumnDefinitions>
Expand Down
55 changes: 55 additions & 0 deletions src/cascadia/TerminalSettingsModel/Profile.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -408,6 +408,61 @@ winrt::hstring Profile::_evaluateIcon() const
return winrt::hstring{ cmdline.c_str() };
}

bool Profile::HasIcon() const
{
return _Icon.has_value();
}

winrt::Microsoft::Terminal::Settings::Model::Profile Profile::IconOverrideSource()
{
for (const auto& parent : _parents)
{
if (auto source{ parent->_getIconOverrideSourceImpl() })
{
return source;
}
}
return nullptr;
}

void Profile::ClearIcon()
{
_Icon = std::nullopt;
_evaluatedIcon = std::nullopt;
}

std::optional<winrt::hstring> Profile::_getIconImpl() const
{
if (_Icon)
{
return _Icon;
}
for (const auto& parent : _parents)
{
if (auto val{ parent->_getIconImpl() })
{
return val;
}
}
return std::nullopt;
}

winrt::Microsoft::Terminal::Settings::Model::Profile Profile::_getIconOverrideSourceImpl() const
{
if (_Icon)
{
return *this;
}
for (const auto& parent : _parents)
{
if (auto source{ parent->_getIconOverrideSourceImpl() })
{
return source;
}
}
return nullptr;
}

// Given a commandLine like the following:
// * "C:\WINDOWS\System32\cmd.exe"
// * "pwsh -WorkingDirectory ~"
Expand Down
8 changes: 6 additions & 2 deletions src/cascadia/TerminalSettingsModel/Profile.h
Original file line number Diff line number Diff line change
Expand Up @@ -113,6 +113,9 @@ namespace winrt::Microsoft::Terminal::Settings::Model::implementation
// Special fields
hstring Icon() const;
void Icon(const hstring& value);
bool HasIcon() const;
Model::Profile IconOverrideSource();
void ClearIcon();

WINRT_PROPERTY(bool, Deleted, false);
WINRT_PROPERTY(OriginTag, Origin, OriginTag::None);
Expand All @@ -128,8 +131,6 @@ namespace winrt::Microsoft::Terminal::Settings::Model::implementation
INHERITABLE_SETTING(Model::Profile, bool, Hidden, false);
INHERITABLE_SETTING(Model::Profile, guid, Guid, _GenerateGuidForProfile(Name(), Source()));
INHERITABLE_SETTING(Model::Profile, hstring, Padding, DEFAULT_PADDING);
// Icon is _very special_ because we want to customize its setter
_BASE_INHERITABLE_SETTING(Model::Profile, std::optional<hstring>, Icon, L"\uE756");

public:
#define PROFILE_SETTINGS_INITIALIZE(type, name, jsonKey, ...) \
Expand All @@ -141,6 +142,7 @@ namespace winrt::Microsoft::Terminal::Settings::Model::implementation
Model::IAppearanceConfig _DefaultAppearance{ winrt::make<AppearanceConfig>(weak_ref<Model::Profile>(*this)) };
Model::FontConfig _FontInfo{ winrt::make<FontConfig>(weak_ref<Model::Profile>(*this)) };

std::optional<hstring> _Icon{ std::nullopt };
std::optional<winrt::hstring> _evaluatedIcon{ std::nullopt };
std::set<std::string> _changeLog;

Expand All @@ -149,6 +151,8 @@ namespace winrt::Microsoft::Terminal::Settings::Model::implementation
static guid _GenerateGuidForProfile(const std::wstring_view& name, const std::wstring_view& source) noexcept;

winrt::hstring _evaluateIcon() const;
std::optional<hstring> _getIconImpl() const;
Model::Profile _getIconOverrideSourceImpl() const;
void _logSettingSet(const std::string_view& setting);
void _logSettingIfSet(const std::string_view& setting, const bool isSet);

Expand Down

0 comments on commit e46ed40

Please sign in to comment.