Polish the Background Image settings (#8778)

## Summary of the Pull Request

Two parts:
* Hide the BG image settings when no image is specified
* Add a checkbox for "Use desktop wallpaper". When that's checked, the BG image path input is hidden. Unchecking that box restores the path to what it was before.

## PR Checklist
* [x] Closes #8763
* [x] I work here

## Validation Steps Performed
Tested manually
This commit is contained in:
Mike Griese 2021-01-18 16:34:07 -06:00 committed by GitHub
parent fa0cd8c7ed
commit 2b4b8dd1bd
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
18 changed files with 333 additions and 122 deletions

View file

@ -1,10 +0,0 @@
// Copyright (c) Microsoft Corporation.
// Licensed under the MIT license.
namespace Microsoft.Terminal.Settings.Editor
{
runtimeclass ColorToBrushConverter : [default] Windows.UI.Xaml.Data.IValueConverter
{
ColorToBrushConverter();
};
}

View file

@ -1,10 +0,0 @@
// Copyright (c) Microsoft Corporation.
// Licensed under the MIT license.
namespace Microsoft.Terminal.Settings.Editor
{
runtimeclass ColorToHexConverter : [default] Windows.UI.Xaml.Data.IValueConverter
{
ColorToHexConverter();
};
}

View file

@ -0,0 +1,45 @@
// Copyright (c) Microsoft Corporation.
// Licensed under the MIT license.
namespace Microsoft.Terminal.Settings.Editor
{
runtimeclass FontWeightConverter : [default] Windows.UI.Xaml.Data.IValueConverter
{
FontWeightConverter();
};
runtimeclass InvertedBooleanToVisibilityConverter : [default] Windows.UI.Xaml.Data.IValueConverter
{
InvertedBooleanToVisibilityConverter();
};
runtimeclass ColorToBrushConverter : [default] Windows.UI.Xaml.Data.IValueConverter
{
ColorToBrushConverter();
};
runtimeclass ColorToHexConverter : [default] Windows.UI.Xaml.Data.IValueConverter
{
ColorToHexConverter();
};
runtimeclass PercentageConverter : [default] Windows.UI.Xaml.Data.IValueConverter
{
PercentageConverter();
};
runtimeclass StringIsEmptyConverter : [default] Windows.UI.Xaml.Data.IValueConverter
{
StringIsEmptyConverter();
};
runtimeclass StringIsNotDesktopConverter : [default] Windows.UI.Xaml.Data.IValueConverter
{
StringIsNotDesktopConverter();
};
runtimeclass DesktopWallpaperToEmptyStringConverter : [default] Windows.UI.Xaml.Data.IValueConverter
{
DesktopWallpaperToEmptyStringConverter();
};
}

View file

@ -1,10 +0,0 @@
// Copyright (c) Microsoft Corporation.
// Licensed under the MIT license.
namespace Microsoft.Terminal.Settings.Editor
{
runtimeclass FontWeightConverter : [default] Windows.UI.Xaml.Data.IValueConverter
{
FontWeightConverter();
};
}

View file

@ -1,10 +0,0 @@
// Copyright (c) Microsoft Corporation.
// Licensed under the MIT license.
namespace Microsoft.Terminal.Settings.Editor
{
runtimeclass InvertedBooleanToVisibilityConverter : [default] Windows.UI.Xaml.Data.IValueConverter
{
InvertedBooleanToVisibilityConverter();
};
}

View file

@ -36,19 +36,25 @@
<!-- ========================= Headers ======================== -->
<ItemGroup>
<ClInclude Include="ColorToBrushConverter.h">
<DependentUpon>ColorToBrushConverter.idl</DependentUpon>
<DependentUpon>Converters.idl</DependentUpon>
</ClInclude>
<ClInclude Include="ColorToHexConverter.h">
<DependentUpon>ColorToHexConverter.idl</DependentUpon>
<DependentUpon>Converters.idl</DependentUpon>
</ClInclude>
<ClInclude Include="FontWeightConverter.h">
<DependentUpon>FontWeightConverter.idl</DependentUpon>
<DependentUpon>Converters.idl</DependentUpon>
</ClInclude>
<ClInclude Include="InvertedBooleanToVisibilityConverter.h">
<DependentUpon>InvertedBooleanToVisibilityConverter.idl</DependentUpon>
<DependentUpon>Converters.idl</DependentUpon>
</ClInclude>
<ClInclude Include="StringIsEmptyConverter.h">
<DependentUpon>Converters.idl</DependentUpon>
</ClInclude>
<ClInclude Include="StringIsNotDesktopConverter.h">
<DependentUpon>Converters.idl</DependentUpon>
</ClInclude>
<ClInclude Include="PercentageConverter.h">
<DependentUpon>PercentageConverter.idl</DependentUpon>
<DependentUpon>Converters.idl</DependentUpon>
</ClInclude>
<ClInclude Include="EnumEntry.h">
<DependentUpon>EnumEntry.idl</DependentUpon>
@ -109,19 +115,25 @@
<!-- ========================= Cpp Files ======================== -->
<ItemGroup>
<ClCompile Include="ColorToBrushConverter.cpp">
<DependentUpon>ColorToBrushConverter.idl</DependentUpon>
<DependentUpon>Converters.idl</DependentUpon>
</ClCompile>
<ClCompile Include="ColorToHexConverter.cpp">
<DependentUpon>ColorToHexConverter.idl</DependentUpon>
<DependentUpon>Converters.idl</DependentUpon>
</ClCompile>
<ClCompile Include="FontWeightConverter.cpp">
<DependentUpon>FontWeightConverter.idl</DependentUpon>
<DependentUpon>Converters.idl</DependentUpon>
</ClCompile>
<ClCompile Include="InvertedBooleanToVisibilityConverter.cpp">
<DependentUpon>InvertedBooleanToVisibilityConverter.idl</DependentUpon>
<DependentUpon>Converters.idl</DependentUpon>
</ClCompile>
<ClCompile Include="StringIsEmptyConverter.cpp">
<DependentUpon>Converters.idl</DependentUpon>
</ClCompile>
<ClCompile Include="StringIsNotDesktopConverter.cpp">
<DependentUpon>Converters.idl</DependentUpon>
</ClCompile>
<ClCompile Include="PercentageConverter.cpp">
<DependentUpon>PercentageConverter.idl</DependentUpon>
<DependentUpon>Converters.idl</DependentUpon>
</ClCompile>
<ClCompile Include="GlobalAppearance.cpp">
<DependentUpon>GlobalAppearance.xaml</DependentUpon>
@ -154,11 +166,7 @@
</ItemGroup>
<!-- ========================= idl Files ======================== -->
<ItemGroup>
<Midl Include="ColorToBrushConverter.idl" />
<Midl Include="ColorToHexConverter.idl" />
<Midl Include="FontWeightConverter.idl" />
<Midl Include="InvertedBooleanToVisibilityConverter.idl" />
<Midl Include="PercentageConverter.idl" />
<Midl Include="Converters.idl" />
<Midl Include="EnumEntry.idl" />
<Midl Include="GlobalAppearance.idl">
<DependentUpon>GlobalAppearance.xaml</DependentUpon>

View file

@ -16,22 +16,10 @@
<ClInclude Include="Utils.h" />
</ItemGroup>
<ItemGroup>
<Midl Include="ColorToBrushConverter.idl">
<Filter>Converters</Filter>
</Midl>
<Midl Include="ColorToHexConverter.idl">
<Filter>Converters</Filter>
</Midl>
<Midl Include="FontWeightConverter.idl">
<Filter>Converters</Filter>
</Midl>
<Midl Include="InvertedBooleanToVisibilityConverter.idl">
<Filter>Converters</Filter>
</Midl>
<Midl Include="PercentageConverter.idl">
<Filter>Converters</Filter>
</Midl>
<Midl Include="EnumEntry.idl" />
<Midl Include="Converters.idl">
<Filter>Converters</Filter>
</Midl>
</ItemGroup>
<ItemGroup>
<None Include="TerminalSettingsEditor.def" />

View file

@ -1,10 +0,0 @@
// Copyright (c) Microsoft Corporation.
// Licensed under the MIT license.
namespace Microsoft.Terminal.Settings.Editor
{
runtimeclass PercentageConverter : [default] Windows.UI.Xaml.Data.IValueConverter
{
PercentageConverter();
};
}

View file

@ -26,6 +26,37 @@ static const std::array<winrt::guid, 2> InBoxProfileGuids{
namespace winrt::Microsoft::Terminal::Settings::Editor::implementation
{
ProfileViewModel::ProfileViewModel(const Model::Profile& profile) :
_profile{ profile }
{
// Add a property changed handler to our own property changed event.
// When the BackgroundImagePath changes, we _also_ need to change the
// value of UseDesktopBGImage.
//
// We need to do this so if someone manually types "desktopWallpaper"
// into the path TextBox, we properly update the checkbox and stored
// _lastBgImagePath. Without this, then we'll permanently hide the text
// box, prevent it from ever being changed again.
PropertyChanged([this](auto&&, const Data::PropertyChangedEventArgs& args) {
if (args.PropertyName() == L"BackgroundImagePath")
{
_NotifyChanges(L"UseDesktopBGImage", L"BackgroundImageSettingsVisible");
}
else if (args.PropertyName() == L"IsBaseLayer")
{
_NotifyChanges(L"BackgroundImageSettingsVisible");
}
});
// Cache the original BG image path. If the user clicks "Use desktop
// wallpaper", then un-checks it, this is the string we'll restore to
// them.
if (BackgroundImagePath() != L"desktopWallpaper")
{
_lastBgImagePath = BackgroundImagePath();
}
}
bool ProfileViewModel::CanDeleteProfile() const
{
const auto guid{ Guid() };
@ -49,6 +80,40 @@ namespace winrt::Microsoft::Terminal::Settings::Editor::implementation
}
}
bool ProfileViewModel::UseDesktopBGImage()
{
return BackgroundImagePath() == L"desktopWallpaper";
}
void ProfileViewModel::UseDesktopBGImage(const bool useDesktop)
{
if (useDesktop)
{
// Stash the current value of BackgroundImagePath. If the user
// checks and un-checks the "Use desktop wallpaper" button, we want
// the path that we display in the text box to remain unchanged.
//
// Only stash this value if it's not the special "desktopWallpaper"
// value.
if (BackgroundImagePath() != L"desktopWallpaper")
{
_lastBgImagePath = BackgroundImagePath();
}
BackgroundImagePath(L"desktopWallpaper");
}
else
{
// Restore the path we had previously cached. This might be the
// empty string.
BackgroundImagePath(_lastBgImagePath);
}
}
bool ProfileViewModel::BackgroundImageSettingsVisible()
{
return IsBaseLayer() || BackgroundImagePath() != L"";
}
void ProfilePageNavigationState::DeleteProfile()
{
auto deleteProfileArgs{ winrt::make_self<DeleteProfileEventArgs>(_Profile.Guid()) };

View file

@ -15,10 +15,14 @@ namespace winrt::Microsoft::Terminal::Settings::Editor::implementation
struct ProfileViewModel : ProfileViewModelT<ProfileViewModel>, ViewModelHelper<ProfileViewModel>
{
public:
ProfileViewModel(const Model::Profile& profile) :
_profile{ profile } {}
ProfileViewModel(const Model::Profile& profile);
bool CanDeleteProfile() const;
bool UseDesktopBGImage();
void UseDesktopBGImage(const bool useDesktop);
bool BackgroundImageSettingsVisible();
GETSET_PROPERTY(bool, IsBaseLayer, false);
PERMANENT_OBSERVABLE_PROJECTED_SETTING(_profile, Guid);
@ -62,6 +66,7 @@ namespace winrt::Microsoft::Terminal::Settings::Editor::implementation
private:
Model::Profile _profile;
winrt::hstring _lastBgImagePath;
};
struct DeleteProfileEventArgs :

View file

@ -12,6 +12,8 @@ namespace Microsoft.Terminal.Settings.Editor
{
Boolean CanDeleteProfile { get; };
Boolean IsBaseLayer;
Boolean UseDesktopBGImage;
Boolean BackgroundImageSettingsVisible { get; };
OBSERVABLE_PROJECTED_SETTING(String, Name);
OBSERVABLE_PROJECTED_SETTING(Guid, Guid);

View file

@ -30,6 +30,10 @@ the MIT License. See LICENSE in the project root for license information. -->
<local:PercentageConverter x:Key="PercentageConverter"/>
<local:FontWeightConverter x:Key="FontWeightConverter"/>
<local:InvertedBooleanToVisibilityConverter x:Key="InvertedBooleanToVisibilityConverter"/>
<local:StringIsEmptyConverter x:Key="StringIsEmptyConverter"/>
<local:StringIsNotDesktopConverter x:Key="StringIsNotDesktopConverter"/>
<local:DesktopWallpaperToEmptyStringConverter x:Key="DesktopWallpaperToEmptyStringConverter"/>
</ResourceDictionary>
</Page.Resources>
@ -291,19 +295,31 @@ the MIT License. See LICENSE in the project root for license information. -->
<!--Background Image-->
<ContentPresenter Style="{StaticResource SettingContainerStyle}">
<StackPanel Orientation="Horizontal">
<TextBox x:Uid="Profile_BackgroundImage"
x:Name="BackgroundImage"
Text="{x:Bind State.Profile.BackgroundImagePath, Mode=TwoWay}"
Style="{StaticResource TextBoxSettingStyle}"/>
<Button x:Uid="Profile_BackgroundImageBrowse"
Click="BackgroundImage_Click"
Style="{StaticResource BrowseButtonStyle}"/>
</ContentPresenter>
<ContentPresenter Style="{StaticResource SettingContainerStyle}">
<StackPanel Orientation="Vertical">
<StackPanel Orientation="Horizontal">
<TextBox x:Uid="Profile_BackgroundImage"
x:Name="BackgroundImage"
Text="{x:Bind State.Profile.BackgroundImagePath, Mode=TwoWay, Converter={StaticResource DesktopWallpaperToEmptyStringConverter}}"
IsEnabled="{x:Bind State.Profile.BackgroundImagePath, Mode=OneWay, Converter={StaticResource StringIsNotDesktopConverter}}"
Style="{StaticResource TextBoxSettingStyle}"/>
<Button x:Uid="Profile_BackgroundImageBrowse"
Click="BackgroundImage_Click"
IsEnabled="{x:Bind State.Profile.BackgroundImagePath, Mode=OneWay, Converter={StaticResource StringIsNotDesktopConverter}}"
Style="{StaticResource BrowseButtonStyle}"/>
</StackPanel>
<CheckBox x:Uid="Profile_UseDesktopImage"
x:Name="UseDesktopImageCheckBox"
IsChecked="{x:Bind State.Profile.UseDesktopBGImage, Mode=TwoWay}"
Style="{StaticResource CheckBoxSettingStyle}"/>
</StackPanel>
</ContentPresenter>
<!--Background Image Stretch Mode-->
<ContentPresenter Style="{StaticResource SettingContainerStyle}">
<ContentPresenter Style="{StaticResource SettingContainerStyle}"
Visibility="{x:Bind State.Profile.BackgroundImageSettingsVisible, Mode=OneWay}">
<muxc:RadioButtons x:Uid="Profile_BackgroundImageStretchMode"
ItemsSource="{x:Bind BackgroundImageStretchModeList, Mode=OneWay}"
SelectedItem="{x:Bind CurrentBackgroundImageStretchMode, Mode=TwoWay}"
@ -312,7 +328,8 @@ the MIT License. See LICENSE in the project root for license information. -->
</ContentPresenter>
<!--Background Image Alignment-->
<ContentPresenter Style="{StaticResource SettingContainerStyle}">
<ContentPresenter Style="{StaticResource SettingContainerStyle}"
Visibility="{x:Bind State.Profile.BackgroundImageSettingsVisible, Mode=OneWay}">
<StackPanel HorizontalAlignment="Left">
<TextBlock x:Uid="Profile_BackgroundImageAlignment"
Style="{StaticResource CustomSettingHeaderStyle}"
@ -468,7 +485,8 @@ the MIT License. See LICENSE in the project root for license information. -->
</ContentPresenter>
<!--Background Image Opacity-->
<ContentPresenter Style="{StaticResource SettingContainerStyle}">
<ContentPresenter Style="{StaticResource SettingContainerStyle}"
Visibility="{x:Bind State.Profile.BackgroundImageSettingsVisible, Mode=OneWay}">
<StackPanel>
<TextBlock x:Uid="Profile_BackgroundImageOpacity"
Style="{StaticResource SliderHeaderStyle}"/>

View file

@ -1,17 +1,17 @@
<?xml version="1.0" encoding="utf-8"?>
<root>
<!--
Microsoft ResX Schema
<!--
Microsoft ResX Schema
Version 2.0
The primary goals of this format is to allow a simple XML format
that is mostly human readable. The generation and parsing of the
various data types are done through the TypeConverter classes
The primary goals of this format is to allow a simple XML format
that is mostly human readable. The generation and parsing of the
various data types are done through the TypeConverter classes
associated with the data types.
Example:
... ado.net/XML headers & schema ...
<resheader name="resmimetype">text/microsoft-resx</resheader>
<resheader name="version">2.0</resheader>
@ -26,36 +26,36 @@
<value>[base64 mime encoded string representing a byte array form of the .NET Framework object]</value>
<comment>This is a comment</comment>
</data>
There are any number of "resheader" rows that contain simple
There are any number of "resheader" rows that contain simple
name/value pairs.
Each data row contains a name, and value. The row also contains a
type or mimetype. Type corresponds to a .NET class that support
text/value conversion through the TypeConverter architecture.
Classes that don't support this are serialized and stored with the
Each data row contains a name, and value. The row also contains a
type or mimetype. Type corresponds to a .NET class that support
text/value conversion through the TypeConverter architecture.
Classes that don't support this are serialized and stored with the
mimetype set.
The mimetype is used for serialized objects, and tells the
ResXResourceReader how to depersist the object. This is currently not
The mimetype is used for serialized objects, and tells the
ResXResourceReader how to depersist the object. This is currently not
extensible. For a given mimetype the value must be set accordingly:
Note - application/x-microsoft.net.object.binary.base64 is the format
that the ResXResourceWriter will generate, however the reader can
Note - application/x-microsoft.net.object.binary.base64 is the format
that the ResXResourceWriter will generate, however the reader can
read any of the formats listed below.
mimetype: application/x-microsoft.net.object.binary.base64
value : The object must be serialized with
value : The object must be serialized with
: System.Runtime.Serialization.Formatters.Binary.BinaryFormatter
: and then encoded with base64 encoding.
mimetype: application/x-microsoft.net.object.soap.base64
value : The object must be serialized with
value : The object must be serialized with
: System.Runtime.Serialization.Formatters.Soap.SoapFormatter
: and then encoded with base64 encoding.
mimetype: application/x-microsoft.net.object.bytearray.base64
value : The object must be serialized into a byte array
value : The object must be serialized into a byte array
: using a System.ComponentModel.TypeConverter
: and then encoded with base64 encoding.
-->
@ -374,7 +374,7 @@
<value>Sets the background color of the text. Overrides the background from the color scheme.</value>
</data>
<data name="Profile_BackgroundImage.Header" xml:space="preserve">
<value>Background image</value>
<value>Background image path</value>
</data>
<data name="Profile_BackgroundImage.[using:Windows.UI.Xaml.Controls]ToolTipService.ToolTip" xml:space="preserve">
<value>Sets the file location of the image to draw over the window background.</value>
@ -633,6 +633,12 @@
<data name="Profile_UseAcrylic.[using:Windows.UI.Xaml.Controls]ToolTipService.ToolTip" xml:space="preserve">
<value>When checked, the window will have an acrylic background. When unchecked, the window will have a plain, untextured background.</value>
</data>
<data name="Profile_UseDesktopImage.Content" xml:space="preserve">
<value>Use desktop wallpaper</value>
</data>
<data name="Profile_UseDesktopImage.[using:Windows.UI.Xaml.Controls]ToolTipService.ToolTip" xml:space="preserve">
<value>When checked, use the desktop wallpaper image as the background image for the terminal.</value>
</data>
<data name="Settings_ResetSettingsButton.Content" xml:space="preserve">
<value>Discard changes</value>
</data>
@ -842,4 +848,4 @@
<data name="Globals_CopyFormatAll.Content" xml:space="preserve">
<value>Both HTML and RTF</value>
</data>
</root>
</root>

View file

@ -0,0 +1,30 @@
// Copyright (c) Microsoft Corporation.
// Licensed under the MIT license.
#include "pch.h"
#include "StringIsEmptyConverter.h"
#include "StringIsEmptyConverter.g.cpp"
using namespace winrt::Windows;
using namespace winrt::Windows::UI::Xaml;
using namespace winrt::Windows::UI::Text;
namespace winrt::Microsoft::Terminal::Settings::Editor::implementation
{
Foundation::IInspectable StringIsEmptyConverter::Convert(Foundation::IInspectable const& value,
Windows::UI::Xaml::Interop::TypeName const& /* targetType */,
Foundation::IInspectable const& /* parameter */,
hstring const& /* language */)
{
const auto& name = winrt::unbox_value_or<hstring>(value, L"");
return winrt::box_value(name.empty() ? Visibility::Collapsed : Visibility::Visible);
}
Foundation::IInspectable StringIsEmptyConverter::ConvertBack(Foundation::IInspectable const& /*value*/,
Windows::UI::Xaml::Interop::TypeName const& /* targetType */,
Foundation::IInspectable const& /*parameter*/,
hstring const& /* language */)
{
throw hresult_not_implemented();
}
}

View file

@ -0,0 +1,9 @@
// Copyright (c) Microsoft Corporation.
// Licensed under the MIT license.
#pragma once
#include "StringIsEmptyConverter.g.h"
#include "../inc/cppwinrt_utils.h"
DECLARE_CONVERTER(winrt::Microsoft::Terminal::Settings::Editor, StringIsEmptyConverter);

View file

@ -0,0 +1,50 @@
// Copyright (c) Microsoft Corporation.
// Licensed under the MIT license.
#include "pch.h"
#include "StringIsNotDesktopConverter.h"
#include "StringIsNotDesktopConverter.g.cpp"
#include "DesktopWallpaperToEmptyStringConverter.g.cpp"
using namespace winrt::Windows;
using namespace winrt::Windows::UI::Xaml;
using namespace winrt::Windows::UI::Text;
namespace winrt::Microsoft::Terminal::Settings::Editor::implementation
{
Foundation::IInspectable StringIsNotDesktopConverter::Convert(Foundation::IInspectable const& value,
Windows::UI::Xaml::Interop::TypeName const& /* targetType */,
Foundation::IInspectable const& /* parameter */,
hstring const& /* language */)
{
// Returns Visible if the string is _not_ "desktopWallpaper", else returns Collapsed
const auto& name = winrt::unbox_value_or<hstring>(value, L"");
return winrt::box_value(name != L"desktopWallpaper");
}
Foundation::IInspectable StringIsNotDesktopConverter::ConvertBack(Foundation::IInspectable const& /*value*/,
Windows::UI::Xaml::Interop::TypeName const& /* targetType */,
Foundation::IInspectable const& /*parameter*/,
hstring const& /* language */)
{
throw hresult_not_implemented();
}
Foundation::IInspectable DesktopWallpaperToEmptyStringConverter::Convert(Foundation::IInspectable const& value,
Windows::UI::Xaml::Interop::TypeName const& /* targetType */,
Foundation::IInspectable const& /* parameter */,
hstring const& /* language */)
{
// Returns the empty string if the string is "desktopWallpaper", else returns the original value.
const auto& name = winrt::unbox_value_or<hstring>(value, L"");
return winrt::box_value(name == L"desktopWallpaper" ? L"" : name);
}
Foundation::IInspectable DesktopWallpaperToEmptyStringConverter::ConvertBack(Foundation::IInspectable const& value,
Windows::UI::Xaml::Interop::TypeName const& /* targetType */,
Foundation::IInspectable const& /*parameter*/,
hstring const& /* language */)
{
return value;
}
}

View file

@ -0,0 +1,11 @@
// Copyright (c) Microsoft Corporation.
// Licensed under the MIT license.
#pragma once
#include "StringIsNotDesktopConverter.g.h"
#include "DesktopWallpaperToEmptyStringConverter.g.h"
#include "../inc/cppwinrt_utils.h"
DECLARE_CONVERTER(winrt::Microsoft::Terminal::Settings::Editor, StringIsNotDesktopConverter);
DECLARE_CONVERTER(winrt::Microsoft::Terminal::Settings::Editor, DesktopWallpaperToEmptyStringConverter);

View file

@ -185,3 +185,27 @@ std::vector<wil::com_ptr<T>> SafeArrayToOwningVector(SAFEARRAY* safeArray)
return result;
}
#define DECLARE_CONVERTER(nameSpace, className) \
namespace nameSpace::implementation \
{ \
struct className : className##T<className> \
{ \
className() = default; \
\
Windows::Foundation::IInspectable Convert(Windows::Foundation::IInspectable const& value, \
Windows::UI::Xaml::Interop::TypeName const& targetType, \
Windows::Foundation::IInspectable const& parameter, \
hstring const& language); \
\
Windows::Foundation::IInspectable ConvertBack(Windows::Foundation::IInspectable const& value, \
Windows::UI::Xaml::Interop::TypeName const& targetType, \
Windows::Foundation::IInspectable const& parameter, \
hstring const& language); \
}; \
} \
\
namespace nameSpace::factory_implementation \
{ \
BASIC_FACTORY(className); \
}\