Allow creating and editing unfocused appearances in the SUI (#10317)

## Summary of the Pull Request
Adds unfocused appearance creation/configuration in the SUI

There is now an 'Unfocused Appearance' section at the bottom of the 'Appearance' tab in a profile. There is a '+' button to create an unfocused appearance if one does not exist, or a delete button to delete the unfocused appearance if one exists (only one of these buttons is visible at a time). 

## PR Checklist
* [ ] Closes #xxx
* [x] CLA signed. If not, go over [here](https://cla.opensource.microsoft.com/microsoft/Terminal) and sign the CLA
* [ ] Tests added/passed
* [ ] Documentation updated. If checked, please file a pull request on [our docs repo](https://github.com/MicrosoftDocs/terminal) and link it here: #xxx
* [ ] Schema updated.
* [x] I work here

## Validation Steps Performed
![unfocusedSUI](https://user-images.githubusercontent.com/26824113/125523613-48aefe28-b4cf-46a2-91c9-2ba3ea89e071.gif)
This commit is contained in:
PankajBhojwani 2021-07-13 16:33:22 -07:00 committed by GitHub
parent 32fbd4cbb6
commit d13c37cd60
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
13 changed files with 258 additions and 4 deletions

View file

@ -257,6 +257,20 @@ namespace winrt::Microsoft::Terminal::Settings::Editor::implementation
_PropertyChangedHandlers(*this, PropertyChangedEventArgs{ L"UsingMonospaceFont" });
}
});
// make sure to send all the property changed events once here
// we do this in the case an old appearance was deleted and then a new one is created,
// the old settings need to be updated in xaml
_PropertyChangedHandlers(*this, PropertyChangedEventArgs{ L"CurrentCursorShape" });
_PropertyChangedHandlers(*this, PropertyChangedEventArgs{ L"IsVintageCursor" });
_PropertyChangedHandlers(*this, PropertyChangedEventArgs{ L"CurrentColorScheme" });
_PropertyChangedHandlers(*this, PropertyChangedEventArgs{ L"CurrentBackgroundImageStretchMode" });
_UpdateBIAlignmentControl(static_cast<int32_t>(Appearance().BackgroundImageAlignment()));
_PropertyChangedHandlers(*this, PropertyChangedEventArgs{ L"CurrentFontWeight" });
_PropertyChangedHandlers(*this, PropertyChangedEventArgs{ L"IsCustomFontWeight" });
_PropertyChangedHandlers(*this, PropertyChangedEventArgs{ L"CurrentFontFace" });
_PropertyChangedHandlers(*this, PropertyChangedEventArgs{ L"ShowAllFonts" });
_PropertyChangedHandlers(*this, PropertyChangedEventArgs{ L"UsingMonospaceFont" });
}
}

View file

@ -59,6 +59,7 @@ namespace winrt::Microsoft::Terminal::Settings::Editor::implementation
Windows::Foundation::Collections::IMapView<hstring, Model::ColorScheme> Schemes() { return _Schemes; }
void Schemes(const Windows::Foundation::Collections::IMapView<hstring, Model::ColorScheme>& val) { _Schemes = val; }
WINRT_PROPERTY(bool, IsDefault, false);
WINRT_PROPERTY(IHostedInWindow, WindowRoot, nullptr);
// These settings are not defined in AppearanceConfig, so we grab them

View file

@ -21,6 +21,8 @@ namespace Microsoft.Terminal.Settings.Editor
runtimeclass AppearanceViewModel : Windows.UI.Xaml.Data.INotifyPropertyChanged
{
Boolean IsDefault;
Boolean UseDesktopBGImage;
Boolean BackgroundImageSettingsVisible { get; };

View file

@ -74,7 +74,8 @@
<local:SettingContainer x:Uid="Profile_FontFace"
ClearSettingValue="{x:Bind Appearance.ClearFontFace}"
HasSettingValue="{x:Bind Appearance.HasFontFace, Mode=OneWay}"
SettingOverrideSource="{x:Bind Appearance.FontFaceOverrideSource, Mode=OneWay}">
SettingOverrideSource="{x:Bind Appearance.FontFaceOverrideSource, Mode=OneWay}"
Visibility="{x:Bind Appearance.IsDefault, Mode=OneWay}">
<StackPanel>
<!--
Binding the ItemsSource to a separate variable that switches between the
@ -104,7 +105,8 @@
<local:SettingContainer x:Uid="Profile_FontSize"
ClearSettingValue="{x:Bind Appearance.ClearFontSize}"
HasSettingValue="{x:Bind Appearance.HasFontSize, Mode=OneWay}"
SettingOverrideSource="{x:Bind Appearance.FontSizeOverrideSource, Mode=OneWay}">
SettingOverrideSource="{x:Bind Appearance.FontSizeOverrideSource, Mode=OneWay}"
Visibility="{x:Bind Appearance.IsDefault, Mode=OneWay}">
<muxc:NumberBox AcceptsExpression="False"
LargeChange="10"
Maximum="128"
@ -119,7 +121,8 @@
x:Uid="Profile_FontWeight"
ClearSettingValue="{x:Bind Appearance.ClearFontWeight}"
HasSettingValue="{x:Bind Appearance.HasFontWeight, Mode=OneWay}"
SettingOverrideSource="{x:Bind Appearance.FontWeightOverrideSource, Mode=OneWay}">
SettingOverrideSource="{x:Bind Appearance.FontWeightOverrideSource, Mode=OneWay}"
Visibility="{x:Bind Appearance.IsDefault, Mode=OneWay}">
<StackPanel>
<ComboBox x:Name="FontWeightComboBox"
ItemTemplate="{StaticResource EnumComboBoxItemTemplate}"

View file

@ -32,7 +32,8 @@ namespace winrt::Microsoft::Terminal::Settings::Editor::implementation
_profile{ profile },
_defaultAppearanceViewModel{ winrt::make<implementation::AppearanceViewModel>(profile.DefaultAppearance().try_as<AppearanceConfig>()) },
_originalProfileGuid{ profile.Guid() },
_appSettings{ appSettings }
_appSettings{ appSettings },
_unfocusedAppearanceViewModel{ nullptr }
{
// Add a property changed handler to our own property changed event.
// This propagates changes from the settings model to anybody listening to our
@ -63,6 +64,13 @@ namespace winrt::Microsoft::Terminal::Settings::Editor::implementation
{
UpdateFontList();
}
if (profile.HasUnfocusedAppearance())
{
_unfocusedAppearanceViewModel = winrt::make<implementation::AppearanceViewModel>(profile.UnfocusedAppearance().try_as<AppearanceConfig>());
}
_defaultAppearanceViewModel.IsDefault(true);
}
Model::TerminalSettings ProfileViewModel::TermSettings() const
@ -239,6 +247,51 @@ namespace winrt::Microsoft::Terminal::Settings::Editor::implementation
return _defaultAppearanceViewModel;
}
bool ProfileViewModel::HasUnfocusedAppearance()
{
return _profile.HasUnfocusedAppearance();
}
bool ProfileViewModel::EditableUnfocusedAppearance()
{
if constexpr (Feature_EditableUnfocusedAppearance::IsEnabled())
{
return true;
}
return false;
}
bool ProfileViewModel::ShowUnfocusedAppearance()
{
return EditableUnfocusedAppearance() && HasUnfocusedAppearance();
}
void ProfileViewModel::CreateUnfocusedAppearance(const Windows::Foundation::Collections::IMapView<hstring, Model::ColorScheme>& schemes,
const IHostedInWindow& windowRoot)
{
_profile.CreateUnfocusedAppearance();
_unfocusedAppearanceViewModel = winrt::make<implementation::AppearanceViewModel>(_profile.UnfocusedAppearance().try_as<AppearanceConfig>());
_unfocusedAppearanceViewModel.Schemes(schemes);
_unfocusedAppearanceViewModel.WindowRoot(windowRoot);
_NotifyChanges(L"UnfocusedAppearance", L"HasUnfocusedAppearance");
}
void ProfileViewModel::DeleteUnfocusedAppearance()
{
_profile.DeleteUnfocusedAppearance();
_unfocusedAppearanceViewModel = nullptr;
_NotifyChanges(L"HasUnfocusedAppearance");
}
Editor::AppearanceViewModel ProfileViewModel::UnfocusedAppearance()
{
return _unfocusedAppearanceViewModel;
}
bool ProfileViewModel::UseParentProcessDirectory()
{
return StartingDirectory().empty();
@ -291,6 +344,16 @@ namespace winrt::Microsoft::Terminal::Settings::Editor::implementation
_DeleteProfileHandlers(*this, *deleteProfileArgs);
}
void ProfilePageNavigationState::CreateUnfocusedAppearance()
{
_Profile.CreateUnfocusedAppearance(_Schemes, _WindowRoot);
}
void ProfilePageNavigationState::DeleteUnfocusedAppearance()
{
_Profile.DeleteUnfocusedAppearance();
}
Profiles::Profiles() :
_previewControl{ Control::TermControl(Model::TerminalSettings{}, make<PreviewConnection>()) }
{
@ -423,6 +486,16 @@ namespace winrt::Microsoft::Terminal::Settings::Editor::implementation
state->DeleteProfile();
}
void Profiles::CreateUnfocusedAppearance_Click(IInspectable const& /*sender*/, RoutedEventArgs const& /*e*/)
{
_State.CreateUnfocusedAppearance();
}
void Profiles::DeleteUnfocusedAppearance_Click(IInspectable const& /*sender*/, RoutedEventArgs const& /*e*/)
{
_State.DeleteUnfocusedAppearance();
}
fire_and_forget Profiles::Icon_Click(IInspectable const&, RoutedEventArgs const&)
{
auto lifetime = get_strong();

View file

@ -34,6 +34,15 @@ namespace winrt::Microsoft::Terminal::Settings::Editor::implementation
winrt::guid OriginalProfileGuid() const noexcept;
bool CanDeleteProfile() const;
Editor::AppearanceViewModel DefaultAppearance();
Editor::AppearanceViewModel UnfocusedAppearance();
bool HasUnfocusedAppearance();
bool EditableUnfocusedAppearance();
bool ShowUnfocusedAppearance();
void CreateUnfocusedAppearance(const Windows::Foundation::Collections::IMapView<hstring, Model::ColorScheme>& schemes,
const IHostedInWindow& windowRoot);
void DeleteUnfocusedAppearance();
WINRT_PROPERTY(bool, IsBaseLayer, false);
PERMANENT_OBSERVABLE_PROJECTED_SETTING(_profile, Guid);
@ -77,6 +86,7 @@ namespace winrt::Microsoft::Terminal::Settings::Editor::implementation
static Editor::Font _GetFont(com_ptr<IDWriteLocalizedStrings> localizedFamilyNames);
Model::CascadiaSettings _appSettings;
Editor::AppearanceViewModel _unfocusedAppearanceViewModel;
};
struct DeleteProfileEventArgs :
@ -100,6 +110,7 @@ namespace winrt::Microsoft::Terminal::Settings::Editor::implementation
const Editor::ProfilePageNavigationState& lastState,
const IHostedInWindow& windowRoot) :
_Profile{ viewModel },
_Schemes{ schemes },
_WindowRoot{ windowRoot }
{
// If there was a previous nav state copy the selected pivot from it.
@ -109,14 +120,27 @@ namespace winrt::Microsoft::Terminal::Settings::Editor::implementation
}
viewModel.DefaultAppearance().Schemes(schemes);
viewModel.DefaultAppearance().WindowRoot(windowRoot);
if (viewModel.UnfocusedAppearance())
{
viewModel.UnfocusedAppearance().Schemes(schemes);
viewModel.UnfocusedAppearance().WindowRoot(windowRoot);
}
}
void DeleteProfile();
void CreateUnfocusedAppearance();
void DeleteUnfocusedAppearance();
Windows::Foundation::Collections::IMapView<hstring, Model::ColorScheme> Schemes() { return _Schemes; }
void Schemes(const Windows::Foundation::Collections::IMapView<hstring, Model::ColorScheme>& val) { _Schemes = val; }
TYPED_EVENT(DeleteProfile, Editor::ProfilePageNavigationState, Editor::DeleteProfileEventArgs);
WINRT_PROPERTY(IHostedInWindow, WindowRoot, nullptr);
WINRT_PROPERTY(Editor::ProfilesPivots, LastActivePivot, Editor::ProfilesPivots::General);
WINRT_PROPERTY(Editor::ProfileViewModel, Profile, nullptr);
private:
Windows::Foundation::Collections::IMapView<hstring, Model::ColorScheme> _Schemes;
};
struct Profiles : ProfilesT<Profiles>
@ -138,6 +162,8 @@ namespace winrt::Microsoft::Terminal::Settings::Editor::implementation
fire_and_forget Icon_Click(Windows::Foundation::IInspectable const& sender, Windows::UI::Xaml::RoutedEventArgs const& e);
void DeleteConfirmation_Click(Windows::Foundation::IInspectable const& sender, Windows::UI::Xaml::RoutedEventArgs const& e);
void Pivot_SelectionChanged(Windows::Foundation::IInspectable const& sender, Windows::UI::Xaml::RoutedEventArgs const& e);
void CreateUnfocusedAppearance_Click(Windows::Foundation::IInspectable const& sender, Windows::UI::Xaml::RoutedEventArgs const& e);
void DeleteUnfocusedAppearance_Click(Windows::Foundation::IInspectable const& sender, Windows::UI::Xaml::RoutedEventArgs const& e);
WINRT_CALLBACK(PropertyChanged, Windows::UI::Xaml::Data::PropertyChangedEventHandler);

View file

@ -25,6 +25,13 @@ namespace Microsoft.Terminal.Settings.Editor
Boolean UseCustomStartingDirectory { get; };
AppearanceViewModel DefaultAppearance { get; };
Guid OriginalProfileGuid { get; };
Boolean HasUnfocusedAppearance { get; };
Boolean EditableUnfocusedAppearance { get; };
Boolean ShowUnfocusedAppearance { get; };
AppearanceViewModel UnfocusedAppearance { get; };
void CreateUnfocusedAppearance(Windows.Foundation.Collections.IMapView<String, Microsoft.Terminal.Settings.Model.ColorScheme> Schemes, IHostedInWindow WindowRoot);
void DeleteUnfocusedAppearance();
OBSERVABLE_PROJECTED_PROFILE_SETTING(String, Name);
PERMANENT_OBSERVABLE_PROJECTED_SETTING(Guid, Guid);
@ -74,6 +81,9 @@ namespace Microsoft.Terminal.Settings.Editor
ProfileViewModel Profile;
ProfilesPivots LastActivePivot;
void CreateUnfocusedAppearance();
void DeleteUnfocusedAppearance();
event Windows.Foundation.TypedEventHandler<ProfilePageNavigationState, DeleteProfileEventArgs> DeleteProfile;
};

View file

@ -33,6 +33,7 @@
<TextBlock FontFamily="{x:Bind Name}"
Text="{x:Bind LocalizedName}" />
</DataTemplate>
<local:ColorToBrushConverter x:Key="ColorToBrushConverter" />
<local:PercentageConverter x:Key="PercentageConverter" />
<local:PercentageSignConverter x:Key="PercentageSignConverter" />
@ -323,6 +324,84 @@
SelectedItem="{x:Bind CurrentScrollState, Mode=TwoWay}" />
</local:SettingContainer>
</StackPanel>
<StackPanel>
<StackPanel Orientation="Horizontal"
Visibility="{x:Bind State.Profile.EditableUnfocusedAppearance, Mode=OneWay}">
<TextBlock x:Uid="Profile_UnfocusedAppearanceTextBlock"
Style="{StaticResource TitleTextBlockStyle}" />
<Button x:Uid="Profile_CreateUnfocusedAppearanceButton"
Margin="32,0,0,0"
Click="CreateUnfocusedAppearance_Click"
Style="{StaticResource BaseButtonStyle}"
Visibility="{x:Bind State.Profile.HasUnfocusedAppearance, Mode=OneWay, Converter={StaticResource InvertedBooleanToVisibilityConverter}}">
<Button.Content>
<FontIcon FontSize="{StaticResource StandardIconSize}"
Glyph="&#xE710;" />
</Button.Content>
</Button>
<Button x:Uid="Profile_DeleteUnfocusedAppearanceButton"
Margin="32,0,0,0"
Click="DeleteUnfocusedAppearance_Click"
Style="{StaticResource BaseButtonStyle}"
Visibility="{x:Bind State.Profile.HasUnfocusedAppearance, Mode=OneWay}">
<Button.Content>
<FontIcon FontSize="{StaticResource StandardIconSize}"
Glyph="&#xE74D;" />
</Button.Content>
<Button.Resources>
<ResourceDictionary>
<ResourceDictionary.ThemeDictionaries>
<ResourceDictionary x:Key="Light">
<SolidColorBrush x:Key="ButtonBackground"
Color="Firebrick" />
<SolidColorBrush x:Key="ButtonBackgroundPointerOver"
Color="#C23232" />
<SolidColorBrush x:Key="ButtonBackgroundPressed"
Color="#A21212" />
<SolidColorBrush x:Key="ButtonForeground"
Color="White" />
<SolidColorBrush x:Key="ButtonForegroundPointerOver"
Color="White" />
<SolidColorBrush x:Key="ButtonForegroundPressed"
Color="White" />
</ResourceDictionary>
<ResourceDictionary x:Key="Dark">
<SolidColorBrush x:Key="ButtonBackground"
Color="Firebrick" />
<SolidColorBrush x:Key="ButtonBackgroundPointerOver"
Color="#C23232" />
<SolidColorBrush x:Key="ButtonBackgroundPressed"
Color="#A21212" />
<SolidColorBrush x:Key="ButtonForeground"
Color="White" />
<SolidColorBrush x:Key="ButtonForegroundPointerOver"
Color="White" />
<SolidColorBrush x:Key="ButtonForegroundPressed"
Color="White" />
</ResourceDictionary>
<ResourceDictionary x:Key="HighContrast">
<SolidColorBrush x:Key="ButtonBackground"
Color="{ThemeResource SystemColorButtonFaceColor}" />
<SolidColorBrush x:Key="ButtonBackgroundPointerOver"
Color="{ThemeResource SystemColorHighlightColor}" />
<SolidColorBrush x:Key="ButtonBackgroundPressed"
Color="{ThemeResource SystemColorHighlightColor}" />
<SolidColorBrush x:Key="ButtonForeground"
Color="{ThemeResource SystemColorButtonTextColor}" />
<SolidColorBrush x:Key="ButtonForegroundPointerOver"
Color="{ThemeResource SystemColorHighlightTextColor}" />
<SolidColorBrush x:Key="ButtonForegroundPressed"
Color="{ThemeResource SystemColorHighlightTextColor}" />
</ResourceDictionary>
</ResourceDictionary.ThemeDictionaries>
</ResourceDictionary>
</Button.Resources>
</Button>
</StackPanel>
<local:Appearances Appearance="{x:Bind State.Profile.UnfocusedAppearance, Mode=OneWay}"
SourceProfile="{x:Bind State.Profile, Mode=OneWay}"
Visibility="{x:Bind State.Profile.ShowUnfocusedAppearance, Mode=OneWay}" />
</StackPanel>
</StackPanel>
</ScrollViewer>
</PivotItem>

View file

@ -791,6 +791,10 @@
<value>Replaces the profile name as the title to pass to the shell on startup.</value>
<comment>A description for what the "tab title" setting does. Presented near "Profile_TabTitle".</comment>
</data>
<data name="Profile_UnfocusedAppearanceTextBlock.Text" xml:space="preserve">
<value>Unfocused Appearance</value>
<comment>The header for the section where the unfocused appearance settings can be changed.</comment>
</data>
<data name="Profile_UseAcrylic.Header" xml:space="preserve">
<value>Enable acrylic</value>
<comment>Header for a control to toggle the acrylic-like rendering of the background. The acrylic material creates a translucent texture.</comment>
@ -1110,6 +1114,14 @@
<value>If checked, show all installed fonts in the list above. Otherwise, only show the list of monospace fonts.</value>
<comment>A description for what the supplementary "show all fonts" setting does. Presented near "Profile_FontFaceShowAllFonts".</comment>
</data>
<data name="Profile_CreateUnfocusedAppearanceButton.[using:Windows.UI.Xaml.Controls]ToolTipService.ToolTip" xml:space="preserve">
<value>Create an unfocused appearance for this profile. This will be the appearance of the profile when it is inactive.</value>
<comment>A description for what the create unfocused appearance button does.</comment>
</data>
<data name="Profile_DeleteUnfocusedAppearanceButton.[using:Windows.UI.Xaml.Controls]ToolTipService.ToolTip" xml:space="preserve">
<value>Delete the unfocused appearance for this profile.</value>
<comment>A description for what the delete unfocused appearance button does.</comment>
</data>
<data name="Actions_DeleteConfirmationButton.Content" xml:space="preserve">
<value>Yes, delete key binding</value>
<comment>Button label that confirms deletion of a key binding entry.</comment>

View file

@ -59,6 +59,27 @@ Profile::Profile(guid guid) :
{
}
void Profile::CreateUnfocusedAppearance()
{
if (!_UnfocusedAppearance)
{
auto unfocusedAppearance{ winrt::make_self<implementation::AppearanceConfig>(weak_ref<Model::Profile>(*this)) };
// If an unfocused appearance is defined in this profile, any undefined parameters are
// taken from this profile's default appearance, so add it as a parent
com_ptr<AppearanceConfig> parentCom;
parentCom.copy_from(winrt::get_self<implementation::AppearanceConfig>(_DefaultAppearance));
unfocusedAppearance->InsertParent(parentCom);
_UnfocusedAppearance = *unfocusedAppearance;
}
}
void Profile::DeleteUnfocusedAppearance()
{
_UnfocusedAppearance = std::nullopt;
}
winrt::com_ptr<Profile> Profile::CopySettings(winrt::com_ptr<Profile> source)
{
auto profile{ winrt::make_self<Profile>() };

View file

@ -79,6 +79,9 @@ namespace winrt::Microsoft::Terminal::Settings::Model::implementation
Profile();
Profile(guid guid);
void CreateUnfocusedAppearance();
void DeleteUnfocusedAppearance();
hstring ToString()
{
return Name();

View file

@ -43,6 +43,9 @@ namespace Microsoft.Terminal.Settings.Model
Profile();
Profile(Guid guid);
void CreateUnfocusedAppearance();
void DeleteUnfocusedAppearance();
OriginTag Origin { get; };
INHERITABLE_PROFILE_SETTING(String, Name);

View file

@ -17,6 +17,13 @@
<alwaysDisabledReleaseTokens/>
</feature>
<feature>
<name>Feature_EditableUnfocusedAppearance</name>
<description>The unfocused appearance section in profiles in the SUI that allows users to create and edit unfocused appearances.</description>
<stage>AlwaysEnabled</stage>
<alwaysDisabledReleaseTokens/>
</feature>
<feature>
<name>Feature_AttemptHandoff</name>
<description>conhost should try to hand connections over to OpenConsole</description>