Skip to content

Commit

Permalink
Represent inheritance in Settings UI (#8919)
Browse files Browse the repository at this point in the history
## Summary of the Pull Request
Introduces the `SettingContainer`. `SettingContainer` is used to wrap a setting in the settings UI and provide the following functionality:
- a reset button next to the header
- tooltips and automation properties for the setting being wrapped
- a comment stating if you are currently overriding a setting

## References
[Spec - Inheritance in Settings UI](https://github.com/microsoft/terminal/blob/main/doc/specs/%231564%20-%20Settings%20UI/cascading-settings.md)
#8804 - removes the ambiguity of leaving a setting blank
#6800 - Settings UI Epic
#8899 - Automation properties for Settings UI
#8768 - Keyboard Navigation

## PR Checklist
* [X] Closes #8804

## Detailed Description of the Pull Request / Additional comments
A few highlights in this PR:
- CommonResources.xaml:
  - we need to merge the SettingContainerStyle.xaml in there. Otherwise, XAML doesn't merge these files properly and can't apply the template.
- Profiles.cpp:
  - view model checks if the starting directory and background image were reset, to determine which value to show when unchecking the special value
  - `Profiles::OnNavigatedTo()` needs a property changed handler to update its own "Current<Setting>" and update the UI properly
- Profiles.xaml:
  - basically wrapped all of the settings we want to be inheritable in there
  - `Binding` is used instead of `x:Bind` in some places because `x:Bind` can't find the parent `SettingContainer` and gives you a compiler error.
- Resources.resw:
  - had to set the "HeaderText" and "HelpText" on each setting container. Does a decent localization burden, unfortunately.
- `SettingContainer` files
  - This operates by creating a template and applying that template over other settings. This allows you to inject the existing controls inside of this. This means that we need to provide our UIElements names and access/modify them via `OnApplyTemplate`
  - We had to remove the header from each individual control, and have `SettingContainer` be in charge of it. This allows us to add the reset button in there.
  - Due to the problem mentioned earlier about CommonResources.xaml, we can't reference anything from CommonResources.xaml.
  - Using `DependencyProperty` to let us set a few properties in the XML files. Particularly, `Has<Setting>` and `Clear<Setting>` are what do all the heavy lifting of interacting with the inheritance model.

## Demo
![Inheritance Demo](https://user-images.githubusercontent.com/11050425/106192086-92a56680-6160-11eb-838c-4ec0beb54965.gif)

## Validation Steps Performed
- Verified correct binding behavior with the following generic setting controls:
  - radio buttons
  - toggle switch
  - text block
  - slider
  - settings with browse buttons
  - the background image alignment control
  - controls with special check boxes (starting directory and background image)

## Next Steps
- The automation properties have been verified using NVDA. This is a part of resolving #8899.
- The override text is currently "Overrides a setting". According to #8269, we actually want to add a hyperlink in there that navigates to the parent profile object. This will be a follow-up task as it requires settings model changes.
  • Loading branch information
carlos-zamora authored Feb 8, 2021
1 parent 3230b18 commit 3b7b200
Show file tree
Hide file tree
Showing 17 changed files with 1,004 additions and 608 deletions.
4 changes: 3 additions & 1 deletion src/cascadia/TerminalControl/TermControl.xaml
Original file line number Diff line number Diff line change
@@ -1,4 +1,6 @@
<UserControl
<!-- 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.TerminalControl.TermControl"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
Expand Down
24 changes: 8 additions & 16 deletions src/cascadia/TerminalSettingsEditor/CommonResources.xaml
Original file line number Diff line number Diff line change
@@ -1,19 +1,20 @@
<ResourceDictionary
<!-- Copyright (c) Microsoft Corporation. All rights reserved. Licensed under
the MIT License. See LICENSE in the project root for license information. -->
<ResourceDictionary
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:muxc="using:Microsoft.UI.Xaml.Controls">

<!--Merge SettingContainerStyle here to give every page access to the SettingContainer-->
<ResourceDictionary.MergedDictionaries>
<ResourceDictionary Source="SettingContainerStyle.xaml"/>
</ResourceDictionary.MergedDictionaries>

<x:Double x:Key="StandardIconSize">14.0</x:Double>
<Thickness x:Key="StandardIndentMargin">13,0,0,0</Thickness>
<Thickness x:Key="StandardControlMargin">0,24,0,0</Thickness>
<x:Double x:Key="StandardBoxMinWidth">250</x:Double>

<!-- This is for easier transition to the SettingsContainer control.
The SettingsContainer will wrap a setting with inheritance UI.-->
<Style x:Key="SettingContainerStyle" TargetType="ContentPresenter">
<Setter Property="Margin" Value="{StaticResource StandardControlMargin}"/>
</Style>

<!-- This is for styling the entire items control used on the
color schemes page-->
<Style x:Key="ItemsControlStyle" TargetType="ItemsControl">
Expand Down Expand Up @@ -44,11 +45,6 @@
<Setter Property="TextWrapping" Value="Wrap"/>
</Style>

<!--Used to create a header for a control-->
<Style x:Key="CustomSettingHeaderStyle" TargetType="TextBlock">
<Setter Property="Margin" Value="0,0,0,4"/>
</Style>

<!--Used for disclaimers-->
<Style x:Key="DisclaimerStyle" TargetType="TextBlock">
<Setter Property="FontStyle" Value="Italic"/>
Expand Down Expand Up @@ -110,10 +106,6 @@
<Setter Property="Margin" Value="5,0,0,0"/>
</Style>

<Style x:Key="SliderHeaderStyle" TargetType="TextBlock" BasedOn="{StaticResource CustomSettingHeaderStyle}">
<Setter Property="HorizontalAlignment" Value="Left"/>
</Style>

<Style x:Key="CustomSliderControlGridStyle" TargetType="Grid">
<Setter Property="Width" Value="{StaticResource StandardBoxMinWidth}"/>
<Setter Property="HorizontalAlignment" Value="Left"/>
Expand Down
51 changes: 22 additions & 29 deletions src/cascadia/TerminalSettingsEditor/GlobalAppearance.xaml
Original file line number Diff line number Diff line change
Expand Up @@ -25,51 +25,44 @@ the MIT License. See LICENSE in the project root for license information. -->
<ScrollViewer>
<StackPanel Style="{StaticResource SettingsStackStyle}">
<!--Theme-->
<ContentPresenter Style="{StaticResource SettingContainerStyle}"
Margin="0">
<muxc:RadioButtons x:Uid="Globals_Theme"
SelectedItem="{x:Bind CurrentTheme, Mode=TwoWay}"
<local:SettingContainer x:Uid="Globals_Theme"
Margin="0">
<muxc:RadioButtons SelectedItem="{x:Bind CurrentTheme, Mode=TwoWay}"
ItemsSource="{x:Bind ThemeList, Mode=OneWay}"
ItemTemplate="{StaticResource EnumRadioButtonTemplate}"/>
</ContentPresenter>
</local:SettingContainer>

<!--Always show tabs-->
<ContentPresenter Style="{StaticResource SettingContainerStyle}">
<ToggleSwitch x:Uid="Globals_AlwaysShowTabs"
IsOn="{x:Bind State.Globals.AlwaysShowTabs, Mode=TwoWay}"/>
</ContentPresenter>
<local:SettingContainer x:Uid="Globals_AlwaysShowTabs">
<ToggleSwitch IsOn="{x:Bind State.Globals.AlwaysShowTabs, Mode=TwoWay}"/>
</local:SettingContainer>

<!--Show Titlebar-->
<ContentPresenter Style="{StaticResource SettingContainerStyle}">
<ToggleSwitch x:Uid="Globals_ShowTitlebar"
IsOn="{x:Bind State.Globals.ShowTabsInTitlebar, Mode=TwoWay}"/>
</ContentPresenter>
<local:SettingContainer x:Uid="Globals_ShowTitlebar">
<ToggleSwitch IsOn="{x:Bind State.Globals.ShowTabsInTitlebar, Mode=TwoWay}"/>
</local:SettingContainer>

<!--Show Title in Titlebar-->
<ContentPresenter Style="{StaticResource SettingContainerStyle}">
<ToggleSwitch x:Uid="Globals_ShowTitleInTitlebar"
IsOn="{x:Bind State.Globals.ShowTitleInTitlebar, Mode=TwoWay}"/>
</ContentPresenter>
<local:SettingContainer x:Uid="Globals_ShowTitleInTitlebar">
<ToggleSwitch IsOn="{x:Bind State.Globals.ShowTitleInTitlebar, Mode=TwoWay}"/>
</local:SettingContainer>

<!--Always on Top-->
<ContentPresenter Style="{StaticResource SettingContainerStyle}">
<ToggleSwitch x:Uid="Globals_AlwaysOnTop"
IsOn="{x:Bind State.Globals.AlwaysOnTop, Mode=TwoWay}"/>
</ContentPresenter>
<local:SettingContainer x:Uid="Globals_AlwaysOnTop">
<ToggleSwitch IsOn="{x:Bind State.Globals.AlwaysOnTop, Mode=TwoWay}"/>
</local:SettingContainer>

<!--Tab Width Mode-->
<ContentPresenter Style="{StaticResource SettingContainerStyle}">
<muxc:RadioButtons x:Uid="Globals_TabWidthMode"
SelectedItem="{x:Bind CurrentTabWidthMode, Mode=TwoWay}"
<local:SettingContainer x:Uid="Globals_TabWidthMode">
<muxc:RadioButtons SelectedItem="{x:Bind CurrentTabWidthMode, Mode=TwoWay}"
ItemsSource="{x:Bind TabWidthModeList, Mode=OneWay}"
ItemTemplate="{StaticResource EnumRadioButtonTemplate}"/>
</ContentPresenter>
</local:SettingContainer>

<!--Disable Animations-->
<ContentPresenter Style="{StaticResource SettingContainerStyle}">
<ToggleSwitch x:Uid="Globals_DisableAnimations"
IsOn="{x:Bind State.Globals.DisableAnimations, Mode=TwoWay}"/>
</ContentPresenter>
<local:SettingContainer x:Uid="Globals_DisableAnimations">
<ToggleSwitch IsOn="{x:Bind State.Globals.DisableAnimations, Mode=TwoWay}"/>
</local:SettingContainer>
</StackPanel>
</ScrollViewer>
</Page>
43 changes: 19 additions & 24 deletions src/cascadia/TerminalSettingsEditor/Interaction.xaml
Original file line number Diff line number Diff line change
Expand Up @@ -15,50 +15,45 @@ the MIT License. See LICENSE in the project root for license information. -->
<ResourceDictionary.MergedDictionaries>
<ResourceDictionary Source="CommonResources.xaml"/>
</ResourceDictionary.MergedDictionaries>

<DataTemplate x:DataType="local:EnumEntry" x:Key="EnumRadioButtonTemplate">
<RadioButton Content="{x:Bind EnumName, Mode=OneWay}"/>
</DataTemplate>
</ResourceDictionary>
</Page.Resources>

<ScrollViewer>
<StackPanel Style="{StaticResource SettingsStackStyle}">
<!--Copy On Select-->
<ContentPresenter Style="{StaticResource SettingContainerStyle}"
Margin="0">
<ToggleSwitch x:Uid="Globals_CopyOnSelect"
IsOn="{x:Bind State.Globals.CopyOnSelect, Mode=TwoWay}"/>
</ContentPresenter>
<local:SettingContainer x:Uid="Globals_CopyOnSelect"
Margin="0">
<ToggleSwitch IsOn="{x:Bind State.Globals.CopyOnSelect, Mode=TwoWay}"/>
</local:SettingContainer>

<!--Copy Format-->
<ContentPresenter Style="{StaticResource SettingContainerStyle}">
<muxc:RadioButtons x:Uid="Globals_CopyFormat"
ItemsSource="{x:Bind CopyFormatList, Mode=OneWay}"
<local:SettingContainer x:Uid="Globals_CopyFormat">
<muxc:RadioButtons ItemsSource="{x:Bind CopyFormatList, Mode=OneWay}"
SelectedItem="{x:Bind CurrentCopyFormat, Mode=TwoWay}"
ItemTemplate="{StaticResource EnumRadioButtonTemplate}"/>
</ContentPresenter>
</local:SettingContainer>

<!--Word Delimiters-->
<ContentPresenter Style="{StaticResource SettingContainerStyle}">
<TextBox x:Uid="Globals_WordDelimiters"
Text="{x:Bind State.Globals.WordDelimiters, Mode=TwoWay}"
<local:SettingContainer x:Uid="Globals_WordDelimiters">
<TextBox Text="{x:Bind State.Globals.WordDelimiters, Mode=TwoWay}"
Style="{StaticResource TextBoxSettingStyle}"/>
</ContentPresenter>
</local:SettingContainer>

<!--Snap On Resize-->
<ContentPresenter Style="{StaticResource SettingContainerStyle}">
<ToggleSwitch x:Uid="Globals_SnapToGridOnResize"
IsOn="{x:Bind State.Globals.SnapToGridOnResize, Mode=TwoWay}"/>
</ContentPresenter>

<local:SettingContainer x:Uid="Globals_SnapToGridOnResize">
<ToggleSwitch IsOn="{x:Bind State.Globals.SnapToGridOnResize, Mode=TwoWay}"/>
</local:SettingContainer>

<!--Tab Switcher Mode-->
<ContentPresenter Style="{StaticResource SettingContainerStyle}">
<muxc:RadioButtons x:Uid="Globals_TabSwitcherMode"
SelectedItem="{x:Bind CurrentTabSwitcherMode, Mode=TwoWay}"
<local:SettingContainer x:Uid="Globals_TabSwitcherMode">
<muxc:RadioButtons SelectedItem="{x:Bind CurrentTabSwitcherMode, Mode=TwoWay}"
ItemsSource="{x:Bind TabSwitcherModeList}"
ItemTemplate="{StaticResource EnumRadioButtonTemplate}"/>
</ContentPresenter>
</local:SettingContainer>
</StackPanel>
</ScrollViewer>
</Page>
55 changes: 25 additions & 30 deletions src/cascadia/TerminalSettingsEditor/Launch.xaml
Original file line number Diff line number Diff line change
Expand Up @@ -33,13 +33,12 @@ the MIT License. See LICENSE in the project root for license information. -->
<StackPanel>
<StackPanel Style="{StaticResource SettingsStackStyle}">
<!--Default Profile-->
<ContentPresenter Style="{StaticResource SettingContainerStyle}"
Margin="0">
<ComboBox x:Uid="Globals_DefaultProfile"
x:Name="DefaultProfile"
ItemsSource="{x:Bind State.Settings.AllProfiles, Mode=OneWay}"
SelectedItem="{x:Bind CurrentDefaultProfile, Mode=TwoWay}"
Style="{StaticResource ComboBoxSettingStyle}">
<local:SettingContainer x:Uid="Globals_DefaultProfile"
Margin="0">
<ComboBox x:Name="DefaultProfile"
ItemsSource="{x:Bind State.Settings.AllProfiles, Mode=OneWay}"
SelectedItem="{x:Bind CurrentDefaultProfile, Mode=TwoWay}"
Style="{StaticResource ComboBoxSettingStyle}">
<ComboBox.ItemTemplate>
<DataTemplate x:DataType="SettingsModel:Profile">
<Grid HorizontalAlignment="Stretch" ColumnSpacing="8">
Expand All @@ -66,42 +65,38 @@ the MIT License. See LICENSE in the project root for license information. -->
</DataTemplate>
</ComboBox.ItemTemplate>
</ComboBox>
</ContentPresenter>
</local:SettingContainer>

<!--Start on User Login-->
<ContentPresenter Style="{StaticResource SettingContainerStyle}">
<ToggleSwitch x:Uid="Globals_StartOnUserLogin"
IsOn="{x:Bind State.Settings.GlobalSettings.StartOnUserLogin, Mode=TwoWay}"/>
</ContentPresenter>
<local:SettingContainer x:Uid="Globals_StartOnUserLogin">
<ToggleSwitch IsOn="{x:Bind State.Settings.GlobalSettings.StartOnUserLogin, Mode=TwoWay}"/>
</local:SettingContainer>

<!--Launch Mode-->
<ContentPresenter Style="{StaticResource SettingContainerStyle}">
<muxc:RadioButtons x:Uid="Globals_LaunchMode"
SelectedItem="{x:Bind CurrentLaunchMode, Mode=TwoWay}"
ItemsSource="{x:Bind LaunchModeList}"
ItemTemplate="{StaticResource EnumRadioButtonTemplate}"/>
</ContentPresenter>
<local:SettingContainer x:Uid="Globals_LaunchMode">
<muxc:RadioButtons SelectedItem="{x:Bind CurrentLaunchMode, Mode=TwoWay}"
ItemsSource="{x:Bind LaunchModeList}"
ItemTemplate="{StaticResource EnumRadioButtonTemplate}"/>
</local:SettingContainer>
</StackPanel>

<!--Launch Size-->
<StackPanel Style="{StaticResource SettingsStackStyle}">
<!--Header-->
<TextBlock x:Uid="Globals_LaunchSize"
Style="{StaticResource SubtitleTextBlockStyle}"/>
Style="{StaticResource SubtitleTextBlockStyle}"/>

<!--Columns-->
<ContentPresenter Style="{StaticResource SettingContainerStyle}"
Margin="0">
<muxc:NumberBox x:Uid="Globals_InitialCols"
Value="{x:Bind State.Settings.GlobalSettings.InitialCols, Mode=TwoWay}"
Style="{StaticResource LaunchSizeNumberBoxStyle}"/>
</ContentPresenter>
<local:SettingContainer x:Uid="Globals_InitialCols"
Margin="0">
<muxc:NumberBox Value="{x:Bind State.Settings.GlobalSettings.InitialCols, Mode=TwoWay}"
Style="{StaticResource LaunchSizeNumberBoxStyle}"/>
</local:SettingContainer>
<!--Rows-->
<ContentPresenter Style="{StaticResource SettingContainerStyle}">
<muxc:NumberBox x:Uid="Globals_InitialRows"
Value="{x:Bind State.Settings.GlobalSettings.InitialRows, Mode=TwoWay}"
Style="{StaticResource LaunchSizeNumberBoxStyle}"/>
</ContentPresenter>
<local:SettingContainer x:Uid="Globals_InitialRows">
<muxc:NumberBox Value="{x:Bind State.Settings.GlobalSettings.InitialRows, Mode=TwoWay}"
Style="{StaticResource LaunchSizeNumberBoxStyle}"/>
</local:SettingContainer>
</StackPanel>
</StackPanel>
</ScrollViewer>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -89,6 +89,9 @@
<ClInclude Include="Rendering.h">
<DependentUpon>Rendering.xaml</DependentUpon>
</ClInclude>
<ClInclude Include="SettingContainer.h">
<DependentUpon>SettingContainer.idl</DependentUpon>
</ClInclude>
<ClInclude Include="Utils.h" />
</ItemGroup>
<!-- ========================= XAML files ======================== -->
Expand Down Expand Up @@ -117,6 +120,9 @@
<Page Include="Rendering.xaml">
<SubType>Designer</SubType>
</Page>
<Page Include="SettingContainerStyle.xaml">
<Type>DefaultStyle</Type>
</Page>
</ItemGroup>
<!-- ========================= Cpp Files ======================== -->
<ItemGroup>
Expand Down Expand Up @@ -174,6 +180,9 @@
<ClCompile Include="Rendering.cpp">
<DependentUpon>Rendering.xaml</DependentUpon>
</ClCompile>
<ClCompile Include="SettingContainer.cpp">
<DependentUpon>SettingContainer.idl</DependentUpon>
</ClCompile>
<ClCompile Include="Utils.cpp" />
</ItemGroup>
<!-- ========================= idl Files ======================== -->
Expand Down Expand Up @@ -207,6 +216,9 @@
<DependentUpon>Profiles.xaml</DependentUpon>
<SubType>Code</SubType>
</Midl>
<Midl Include="SettingContainer.idl">
<SubType>Code</SubType>
</Midl>
</ItemGroup>
<!-- ========================= Misc Files ======================== -->
<ItemGroup>
Expand Down
Loading

0 comments on commit 3b7b200

Please sign in to comment.