Skip to content

Commit 0ba01cc

Browse files
committed
Add Extensions page to Settings UI
1 parent 8598ed7 commit 0ba01cc

File tree

12 files changed

+437
-4
lines changed

12 files changed

+437
-4
lines changed
Lines changed: 125 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,125 @@
1+
// Copyright (c) Microsoft Corporation.
2+
// Licensed under the MIT license.
3+
4+
#include "pch.h"
5+
#include "Extensions.h"
6+
#include "Extensions.g.cpp"
7+
#include "ExtensionsViewModel.g.cpp"
8+
9+
#include <LibraryResources.h>
10+
#include "..\WinRTUtils\inc\Utils.h"
11+
12+
using namespace winrt::Windows::UI::Xaml;
13+
using namespace winrt::Windows::UI::Xaml::Controls;
14+
using namespace winrt::Windows::UI::Xaml::Navigation;
15+
16+
namespace winrt::Microsoft::Terminal::Settings::Editor::implementation
17+
{
18+
Extensions::Extensions()
19+
{
20+
InitializeComponent();
21+
}
22+
23+
void Extensions::OnNavigatedTo(const NavigationEventArgs& e)
24+
{
25+
_ViewModel = e.Parameter().as<Editor::ExtensionsViewModel>();
26+
}
27+
28+
void Extensions::ExtensionLoaded(const Windows::Foundation::IInspectable& sender, const Windows::UI::Xaml::RoutedEventArgs& /*args*/)
29+
{
30+
const auto& toggleSwitch = sender.as<Controls::ToggleSwitch>();
31+
const auto& extensionSource = toggleSwitch.Tag().as<hstring>();
32+
toggleSwitch.IsOn(_ViewModel.GetExtensionState(extensionSource));
33+
}
34+
35+
void Extensions::ExtensionToggled(const Windows::Foundation::IInspectable& sender, const Windows::UI::Xaml::RoutedEventArgs& /*args*/)
36+
{
37+
const auto& toggleSwitch = sender.as<Controls::ToggleSwitch>();
38+
const auto& extensionSource = toggleSwitch.Tag().as<hstring>();
39+
_ViewModel.SetExtensionState(extensionSource, toggleSwitch.IsOn());
40+
}
41+
42+
ExtensionsViewModel::ExtensionsViewModel(const Model::CascadiaSettings& settings) :
43+
_settings{ settings }
44+
{
45+
std::vector<IInspectable> fragmentExtensions;
46+
fragmentExtensions.reserve(settings.FragmentExtensions().Size());
47+
48+
std::vector<IInspectable> profilesModified;
49+
std::vector<IInspectable> profilesAdded;
50+
std::vector<IInspectable> colorSchemesAdded;
51+
for (const auto&& fragExt : settings.FragmentExtensions())
52+
{
53+
fragmentExtensions.push_back(fragExt);
54+
55+
for (const auto&& profile : fragExt.ModifiedProfilesView())
56+
{
57+
profilesModified.push_back(profile);
58+
}
59+
60+
for (const auto&& profile : fragExt.NewProfilesView())
61+
{
62+
profilesAdded.push_back(profile);
63+
}
64+
65+
for (const auto&& scheme : fragExt.ColorSchemesView())
66+
{
67+
colorSchemesAdded.push_back(scheme);
68+
}
69+
}
70+
71+
_fragmentExtensions = single_threaded_observable_vector<IInspectable>(std::move(fragmentExtensions));
72+
_profilesModified = single_threaded_observable_vector<IInspectable>(std::move(profilesModified));
73+
_profilesAdded = single_threaded_observable_vector<IInspectable>(std::move(profilesAdded));
74+
_colorSchemesAdded = single_threaded_observable_vector<IInspectable>(std::move(colorSchemesAdded));
75+
}
76+
77+
// Returns true if the extension is enabled, false otherwise
78+
bool ExtensionsViewModel::GetExtensionState(hstring extensionSource) const
79+
{
80+
if (const auto& disabledExtensions = _DisabledProfileSources())
81+
{
82+
uint32_t ignored;
83+
return !disabledExtensions.IndexOf(extensionSource, ignored);
84+
}
85+
// "disabledProfileSources" not defined --> all extensions are enabled
86+
return true;
87+
}
88+
89+
// Enable/Disable an extension
90+
void ExtensionsViewModel::SetExtensionState(hstring extensionSource, bool enableExt)
91+
{
92+
// get the current status of the extension
93+
uint32_t idx;
94+
bool currentlyEnabled = true;
95+
const auto& disabledExtensions = _DisabledProfileSources();
96+
if (disabledExtensions)
97+
{
98+
currentlyEnabled = !disabledExtensions.IndexOf(extensionSource, idx);
99+
}
100+
101+
// current status mismatches the desired status,
102+
// update the list of disabled extensions
103+
if (currentlyEnabled != enableExt)
104+
{
105+
// If we're disabling an extension and we don't have "disabledProfileSources" defined,
106+
// create it in the model directly
107+
if (!disabledExtensions && !enableExt)
108+
{
109+
std::vector<hstring> disabledProfileSources{ extensionSource };
110+
_settings.GlobalSettings().DisabledProfileSources(single_threaded_vector<hstring>(std::move(disabledProfileSources)));
111+
return;
112+
}
113+
114+
// Update the list of disabled extensions
115+
if (enableExt)
116+
{
117+
disabledExtensions.RemoveAt(idx);
118+
}
119+
else
120+
{
121+
disabledExtensions.Append(extensionSource);
122+
}
123+
}
124+
}
125+
}
Lines changed: 54 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,54 @@
1+
// Copyright (c) Microsoft Corporation.
2+
// Licensed under the MIT license.
3+
4+
#pragma once
5+
6+
#include "Extensions.g.h"
7+
#include "ExtensionsViewModel.g.h"
8+
#include "ViewModelHelpers.h"
9+
#include "Utils.h"
10+
11+
namespace winrt::Microsoft::Terminal::Settings::Editor::implementation
12+
{
13+
struct Extensions : public HasScrollViewer<Extensions>, ExtensionsT<Extensions>
14+
{
15+
public:
16+
Extensions();
17+
18+
void OnNavigatedTo(const Windows::UI::Xaml::Navigation::NavigationEventArgs& e);
19+
void ExtensionLoaded(const Windows::Foundation::IInspectable& sender, const Windows::UI::Xaml::RoutedEventArgs& args);
20+
void ExtensionToggled(const Windows::Foundation::IInspectable& sender, const Windows::UI::Xaml::RoutedEventArgs& args);
21+
22+
WINRT_PROPERTY(Editor::ExtensionsViewModel, ViewModel, nullptr);
23+
};
24+
25+
struct ExtensionsViewModel : ExtensionsViewModelT<ExtensionsViewModel>, ViewModelHelper<ExtensionsViewModel>
26+
{
27+
public:
28+
ExtensionsViewModel(const Model::CascadiaSettings& settings);
29+
30+
// Views
31+
Windows::Foundation::Collections::IVectorView<IInspectable> FragmentExtensions() const noexcept { return _fragmentExtensions.GetView(); }
32+
Windows::Foundation::Collections::IVectorView<IInspectable> ProfilesModified() const noexcept { return _profilesModified.GetView(); }
33+
Windows::Foundation::Collections::IVectorView<IInspectable> ProfilesAdded() const noexcept { return _profilesAdded.GetView(); }
34+
Windows::Foundation::Collections::IVectorView<IInspectable> ColorSchemesAdded() const noexcept { return _colorSchemesAdded.GetView(); }
35+
36+
bool GetExtensionState(hstring extensionSource) const;
37+
void SetExtensionState(hstring extensionSource, bool enableExt);
38+
39+
private:
40+
Model::CascadiaSettings _settings;
41+
Windows::Foundation::Collections::IVector<IInspectable> _fragmentExtensions;
42+
Windows::Foundation::Collections::IVector<IInspectable> _profilesModified;
43+
Windows::Foundation::Collections::IVector<IInspectable> _profilesAdded;
44+
Windows::Foundation::Collections::IVector<IInspectable> _colorSchemesAdded;
45+
46+
Windows::Foundation::Collections::IVector<hstring> _DisabledProfileSources() const noexcept { return _settings.GlobalSettings().DisabledProfileSources(); }
47+
};
48+
};
49+
50+
namespace winrt::Microsoft::Terminal::Settings::Editor::factory_implementation
51+
{
52+
BASIC_FACTORY(Extensions);
53+
BASIC_FACTORY(ExtensionsViewModel);
54+
}
Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,26 @@
1+
// Copyright (c) Microsoft Corporation.
2+
// Licensed under the MIT license.
3+
4+
namespace Microsoft.Terminal.Settings.Editor
5+
{
6+
[default_interface] runtimeclass Extensions : Windows.UI.Xaml.Controls.Page
7+
{
8+
Extensions();
9+
ExtensionsViewModel ViewModel { get; };
10+
}
11+
12+
[default_interface] runtimeclass ExtensionsViewModel : Windows.UI.Xaml.Data.INotifyPropertyChanged
13+
{
14+
ExtensionsViewModel(Microsoft.Terminal.Settings.Model.CascadiaSettings settings);
15+
16+
// Views
17+
Windows.Foundation.Collections.IVectorView<IInspectable> FragmentExtensions { get; };
18+
Windows.Foundation.Collections.IVectorView<IInspectable> ProfilesModified { get; };
19+
Windows.Foundation.Collections.IVectorView<IInspectable> ProfilesAdded { get; };
20+
Windows.Foundation.Collections.IVectorView<IInspectable> ColorSchemesAdded { get; };
21+
22+
// Methods
23+
Boolean GetExtensionState(String extensionSource);
24+
void SetExtensionState(String extensionSource, Boolean enableExt);
25+
}
26+
}
Lines changed: 75 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,75 @@
1+
<!--
2+
Copyright (c) Microsoft Corporation. All rights reserved. Licensed under
3+
the MIT License. See LICENSE in the project root for license information.
4+
-->
5+
<Page x:Class="Microsoft.Terminal.Settings.Editor.Extensions"
6+
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
7+
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
8+
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
9+
xmlns:local="using:Microsoft.Terminal.Settings.Editor"
10+
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
11+
xmlns:model="using:Microsoft.Terminal.Settings.Model"
12+
xmlns:mtu="using:Microsoft.Terminal.UI"
13+
xmlns:muxc="using:Microsoft.UI.Xaml.Controls"
14+
mc:Ignorable="d">
15+
16+
<Page.Resources>
17+
<ResourceDictionary>
18+
<ResourceDictionary.MergedDictionaries>
19+
<ResourceDictionary Source="CommonResources.xaml" />
20+
</ResourceDictionary.MergedDictionaries>
21+
</ResourceDictionary>
22+
</Page.Resources>
23+
24+
<StackPanel Style="{StaticResource SettingsStackStyle}"
25+
Spacing="20">
26+
<StackPanel>
27+
<!-- Grouping: Active Extensions -->
28+
<TextBlock x:Uid="Globals_ActiveExtensionsHeader"
29+
Style="{StaticResource TextBlockSubHeaderStyle}" />
30+
<ItemsControl ItemsSource="{x:Bind ViewModel.FragmentExtensions, Mode=OneWay}">
31+
<ItemsControl.ItemTemplate>
32+
<DataTemplate x:DataType="model:FragmentSettings">
33+
<local:SettingContainer Header="{x:Bind Source}">
34+
<ToggleSwitch Toggled="ExtensionToggled"
35+
Loaded="ExtensionLoaded"
36+
Tag="{x:Bind Source}"
37+
Style="{StaticResource ToggleSwitchInExpanderStyle}" />
38+
</local:SettingContainer>
39+
</DataTemplate>
40+
</ItemsControl.ItemTemplate>
41+
</ItemsControl>
42+
43+
</StackPanel>
44+
45+
<StackPanel>
46+
<!-- Grouping: Modified Profiles -->
47+
<TextBlock x:Uid="Globals_ModifiedProfilesHeader"
48+
Style="{StaticResource TextBlockSubHeaderStyle}" />
49+
<TextBlock FontStyle="Italic">Coming soon!</TextBlock>
50+
51+
<!--TODO CARLOS: ItemsRepeater of Expanders-->
52+
53+
</StackPanel>
54+
55+
<StackPanel>
56+
<!-- Grouping: Added Profiles -->
57+
<TextBlock x:Uid="Globals_AddedProfilesHeader"
58+
Style="{StaticResource TextBlockSubHeaderStyle}" />
59+
<TextBlock FontStyle="Italic">Coming soon!</TextBlock>
60+
61+
<!--TODO CARLOS: ItemsRepeater of Expanders-->
62+
63+
</StackPanel>
64+
65+
<StackPanel>
66+
<!-- Grouping: Added Color Schemes -->
67+
<TextBlock x:Uid="Globals_AddedColorSchemesHeader"
68+
Style="{StaticResource TextBlockSubHeaderStyle}" />
69+
<TextBlock FontStyle="Italic">Coming soon!</TextBlock>
70+
71+
<!--TODO CARLOS: ItemsRepeater of Expanders-->
72+
73+
</StackPanel>
74+
</StackPanel>
75+
</Page>

src/cascadia/TerminalSettingsEditor/MainPage.cpp

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@
99
#include "Compatibility.h"
1010
#include "Rendering.h"
1111
#include "RenderingViewModel.h"
12+
#include "Extensions.h"
1213
#include "Actions.h"
1314
#include "ProfileViewModel.h"
1415
#include "GlobalAppearance.h"
@@ -44,6 +45,7 @@ static const std::wstring_view renderingTag{ L"Rendering_Nav" };
4445
static const std::wstring_view compatibilityTag{ L"Compatibility_Nav" };
4546
static const std::wstring_view actionsTag{ L"Actions_Nav" };
4647
static const std::wstring_view newTabMenuTag{ L"NewTabMenu_Nav" };
48+
static const std::wstring_view extensionsTag{ L"Extensions_Nav" };
4749
static const std::wstring_view globalProfileTag{ L"GlobalProfile_Nav" };
4850
static const std::wstring_view addProfileTag{ L"AddProfile" };
4951
static const std::wstring_view colorSchemesTag{ L"ColorSchemes_Nav" };
@@ -445,6 +447,12 @@ namespace winrt::Microsoft::Terminal::Settings::Editor::implementation
445447
_breadcrumbs.Append(crumb);
446448
}
447449
}
450+
else if (clickedItemTag == extensionsTag)
451+
{
452+
contentFrame().Navigate(xaml_typename<Editor::Extensions>(), winrt::make<ExtensionsViewModel>(_settingsClone));
453+
const auto crumb = winrt::make<Breadcrumb>(box_value(clickedItemTag), RS_(L"Nav_Extensions/Content"), BreadcrumbSubPage::None);
454+
_breadcrumbs.Append(crumb);
455+
}
448456
else if (clickedItemTag == globalProfileTag)
449457
{
450458
auto profileVM{ _viewModelForProfile(_settingsClone.ProfileDefaults(), _settingsClone, Dispatcher()) };

src/cascadia/TerminalSettingsEditor/MainPage.xaml

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -154,6 +154,14 @@
154154
<FontIcon Glyph="&#xE71d;" />
155155
</muxc:NavigationViewItem.Icon>
156156
</muxc:NavigationViewItem>
157+
158+
<muxc:NavigationViewItem x:Uid="Nav_Extensions"
159+
Tag="Extensions_Nav">
160+
<muxc:NavigationViewItem.Icon>
161+
<FontIcon Glyph="&#xE74C;" />
162+
<!--Alternative: Puzzle - EA86-->
163+
</muxc:NavigationViewItem.Icon>
164+
</muxc:NavigationViewItem>
157165

158166
<muxc:NavigationViewItemHeader x:Uid="Nav_Profiles" />
159167

src/cascadia/TerminalSettingsEditor/Microsoft.Terminal.Settings.Editor.vcxproj

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -125,6 +125,10 @@
125125
<DependentUpon>NewTabMenuViewModel.idl</DependentUpon>
126126
<SubType>Code</SubType>
127127
</ClInclude>
128+
<ClInclude Include="Extensions.h">
129+
<DependentUpon>Extensions.xaml</DependentUpon>
130+
<SubType>Code</SubType>
131+
</ClInclude>
128132
<ClInclude Include="Profiles_Base.h">
129133
<DependentUpon>Profiles_Base.xaml</DependentUpon>
130134
<SubType>Code</SubType>
@@ -199,6 +203,9 @@
199203
<Page Include="MainPage.xaml">
200204
<SubType>Designer</SubType>
201205
</Page>
206+
<Page Include="Extensions.xaml">
207+
<SubType>Designer</SubType>
208+
</Page>
202209
<Page Include="Profiles_Base.xaml">
203210
<SubType>Designer</SubType>
204211
</Page>
@@ -309,6 +316,10 @@
309316
<DependentUpon>NewTabMenuViewModel.idl</DependentUpon>
310317
<SubType>Code</SubType>
311318
</ClCompile>
319+
<ClCompile Include="Extensions.cpp">
320+
<DependentUpon>Extensions.xaml</DependentUpon>
321+
<SubType>Code</SubType>
322+
</ClCompile>
312323
<ClCompile Include="Profiles_Base.cpp">
313324
<DependentUpon>Profiles_Base.xaml</DependentUpon>
314325
<SubType>Code</SubType>
@@ -408,6 +419,10 @@
408419
<Midl Include="GlobalAppearanceViewModel.idl" />
409420
<Midl Include="LaunchViewModel.idl" />
410421
<Midl Include="NewTabMenuViewModel.idl" />
422+
<Midl Include="Extensions.idl">
423+
<DependentUpon>Extensions.xaml</DependentUpon>
424+
<SubType>Code</SubType>
425+
</Midl>
411426
<Midl Include="Profiles_Base.idl">
412427
<DependentUpon>Profiles_Base.xaml</DependentUpon>
413428
<SubType>Code</SubType>

src/cascadia/TerminalSettingsEditor/Resources/en-US/Resources.resw

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -680,6 +680,10 @@
680680
<value>Actions</value>
681681
<comment>Header for the "actions" menu item. This navigates to a page that lets you see and modify commands, key bindings, and actions that can be done in the app.</comment>
682682
</data>
683+
<data name="Nav_Extensions.Content" xml:space="preserve">
684+
<value>Extensions</value>
685+
<comment>Header for the "extensions" menu item. This navigates to a page that lets you see and modify extensions for the app.</comment>
686+
</data>
683687
<data name="Profile_OpacitySlider.[using:Windows.UI.Xaml.Automation]AutomationProperties.Name" xml:space="preserve">
684688
<value>Background opacity</value>
685689
<comment>Name for a control to determine the level of opacity for the background of the control. The user can choose to make the background of the app more or less opaque.</comment>
@@ -2316,4 +2320,16 @@
23162320
<data name="Profile_Source_Orphaned.HelpText" xml:space="preserve">
23172321
<value>Indicates the software that originally created this profile.</value>
23182322
</data>
2323+
<data name="Globals_ActiveExtensionsHeader.Text" xml:space="preserve">
2324+
<value>Active Extensions</value>
2325+
</data>
2326+
<data name="Globals_ModifiedProfilesHeader.Text" xml:space="preserve">
2327+
<value>Modified Profiles</value>
2328+
</data>
2329+
<data name="Globals_AddedProfilesHeader.Text" xml:space="preserve">
2330+
<value>Added Profiles</value>
2331+
</data>
2332+
<data name="Globals_AddedColorSchemesHeader.Text" xml:space="preserve">
2333+
<value>Added Color Schemes</value>
2334+
</data>
23192335
</root>

0 commit comments

Comments
 (0)