Add support for background image alignment (as one setting) (#1959)

* Implement base background image alignment settings

TerminalSettings now has two new properties:
* BackgroundImageHorizontalAlignment
* BackgroundImageVerticalAlignment

These properties are used in TermControl::_InitializeBackgroundBrush to specify the alignment for TermControl::_bgImageLayer.

This is a base commit that will split into two possible branches:
* Use one setting in profiles.json: "backgroundImageAlignment"
* Use two settings in profiles.json: "backgroundImageHorizontal/VerticalAlignment"

* Implement background image alignment profile setting

Implement background image alignment as one profile setting.
* This has the benefit of acting as a single setting when the user would likely want to change both horizontal and vertical alignment.
* HorizontalAlignment and VerticalAlignment are still stored as a tuple in Profile because they are an optional field. And thus, it would not make sense for one of the alignments to be left unused while the other is not.
* Cons are that the tuple signature is quite long, but it is only used in a small number of locations. The Serialize method is also a little mishapen with the nested switch statements. Empty lines have been added between base-level cases to improve readability.

* Fix capitalization typo for BackgroundImageStretchModeKey

In Profiles.cpp, the key for the image stretch mode json property had a lowercase 'i' in "Backgroundimage", not following proper UpperCamelCase.
The "i" has been capitalized and the two usages of the constant have been updated as well.

* Document Background Image settings

* Adds entries SettingsSchema.md for the original 3 backgroundImage settings in addition to the new backgroundImageAlignment setting.

* Fix setting capitalization error in UsingJsonSettings.md

* The background image example in UsingJsonSettings.md listing a backgroundImageStretchMode of "Fill" has been corrected to "fill".


Fixes #1949.
This commit is contained in:
Robert Jordan 2019-07-25 00:47:06 -04:00 committed by Dustin L. Howett (MSFT)
parent 2c3e175f62
commit 89190c6e6c
8 changed files with 183 additions and 8 deletions

View file

@ -35,6 +35,10 @@ Properties listed below are specific to each unique profile.
| `startingDirectory` | _Required_ | String | `%USERPROFILE%` | The directory the shell starts in when it is loaded. |
| `useAcrylic` | _Required_ | Boolean | `false` | When set to `true`, the window will have an acrylic background. When set to `false`, the window will have a plain, untextured background. |
| `background` | Optional | String | | Sets the background color of the profile. Overrides `background` set in color scheme if `colorscheme` is set. Uses hex color format: `"#rrggbb"`. |
| `backgroundImage` | Optional | String | | Sets the file location of the Image to draw over the window background. |
| `backgroundImageAlignment` | Optional | String | `center` | Sets how the background image aligns to the boundaries of the window. Possible values: `"center"`, `"left"`, `"top"`, `"right"`, `"bottom"`, `"topLeft"`, `"topRight"`, `"bottomLeft"`, `"bottomRight"` |
| `backgroundImageOpacity` | Optional | Number | `1.0` | Sets the transparency of the background image. Accepts floating point values from 0-1. |
| `backgroundImageStretchMode` | Optional | String | `uniformToFill` | Sets how the background image is resized to fill the window. Possible values: `"none"`, `"fill"`, `"uniform"`, `"uniformToFill"` |
| `colorTable` | Optional | Array[String] | | Array of colors used in the profile if `colorscheme` is not set. Colors use hex color format: `"#rrggbb"`. Ordering is as follows: `[black, red, green, yellow, blue, magenta, cyan, white, bright black, bright red, bright green, bright yellow, bright blue, bright magenta, bright cyan, bright white]` |
| `cursorHeight` | Optional | Integer | | Sets the percentage height of the cursor starting from the bottom. Only works when `cursorShape` is set to `"vintage"`. Accepts values from 25-100. |
| `foreground` | Optional | String | | Sets the foreground color of the profile. Overrides `foreground` set in color scheme if `colorscheme` is set. Uses hex color format: `"#rrggbb"`. |

View file

@ -110,7 +110,7 @@ The schema name can then be referenced in one or more profiles.
```json
"backgroundImage": "ms-appdata:///Roaming/openlogo.jpg",
"backgroundImageOpacity": 0.3,
"backgroundImageStretchMode": "Fill",
"backgroundImageStretchMode": "fill",
```
5. Make sure that `useAcrylic` is `false`.
6. Save the file.

View file

@ -38,7 +38,8 @@ static constexpr std::string_view StartingDirectoryKey{ "startingDirectory" };
static constexpr std::string_view IconKey{ "icon" };
static constexpr std::string_view BackgroundImageKey{ "backgroundImage" };
static constexpr std::string_view BackgroundImageOpacityKey{ "backgroundImageOpacity" };
static constexpr std::string_view BackgroundimageStretchModeKey{ "backgroundImageStretchMode" };
static constexpr std::string_view BackgroundImageStretchModeKey{ "backgroundImageStretchMode" };
static constexpr std::string_view BackgroundImageAlignmentKey{ "backgroundImageAlignment" };
// Possible values for Scrollbar state
static constexpr std::wstring_view AlwaysVisible{ L"visible" };
@ -57,6 +58,17 @@ static constexpr std::string_view ImageStretchModeFill{ "fill" };
static constexpr std::string_view ImageStretchModeUniform{ "uniform" };
static constexpr std::string_view ImageStretchModeUniformTofill{ "uniformToFill" };
// Possible values for Image Alignment
static constexpr std::string_view ImageAlignmentCenter{ "center" };
static constexpr std::string_view ImageAlignmentLeft{ "left" };
static constexpr std::string_view ImageAlignmentTop{ "top" };
static constexpr std::string_view ImageAlignmentRight{ "right" };
static constexpr std::string_view ImageAlignmentBottom{ "bottom" };
static constexpr std::string_view ImageAlignmentTopLeft{ "topLeft" };
static constexpr std::string_view ImageAlignmentTopRight{ "topRight" };
static constexpr std::string_view ImageAlignmentBottomLeft{ "bottomLeft" };
static constexpr std::string_view ImageAlignmentBottomRight{ "bottomRight" };
Profile::Profile() :
Profile(Utils::CreateGuid())
{
@ -89,7 +101,8 @@ Profile::Profile(const winrt::guid& guid) :
_icon{},
_backgroundImage{},
_backgroundImageOpacity{},
_backgroundImageStretchMode{}
_backgroundImageStretchMode{},
_backgroundImageAlignment{}
{
}
@ -200,6 +213,14 @@ TerminalSettings Profile::CreateTerminalSettings(const std::vector<ColorScheme>&
terminalSettings.BackgroundImageStretchMode(_backgroundImageStretchMode.value());
}
if (_backgroundImageAlignment)
{
const auto imageHorizontalAlignment = std::get<winrt::Windows::UI::Xaml::HorizontalAlignment>(_backgroundImageAlignment.value());
const auto imageVerticalAlignment = std::get<winrt::Windows::UI::Xaml::VerticalAlignment>(_backgroundImageAlignment.value());
terminalSettings.BackgroundImageHorizontalAlignment(imageHorizontalAlignment);
terminalSettings.BackgroundImageVerticalAlignment(imageVerticalAlignment);
}
return terminalSettings;
}
@ -293,7 +314,12 @@ Json::Value Profile::ToJson() const
if (_backgroundImageStretchMode)
{
root[JsonKey(BackgroundimageStretchModeKey)] = SerializeImageStretchMode(_backgroundImageStretchMode.value()).data();
root[JsonKey(BackgroundImageStretchModeKey)] = SerializeImageStretchMode(_backgroundImageStretchMode.value()).data();
}
if (_backgroundImageAlignment)
{
root[JsonKey(BackgroundImageAlignmentKey)] = SerializeImageAlignment(_backgroundImageAlignment.value()).data();
}
return root;
@ -428,10 +454,14 @@ Profile Profile::FromJson(const Json::Value& json)
{
result._backgroundImageOpacity = backgroundImageOpacity.asFloat();
}
if (auto backgroundImageStretchMode{ json[JsonKey(BackgroundimageStretchModeKey)] })
if (auto backgroundImageStretchMode{ json[JsonKey(BackgroundImageStretchModeKey)] })
{
result._backgroundImageStretchMode = ParseImageStretchMode(backgroundImageStretchMode.asString());
}
if (auto backgroundImageAlignment{ json[JsonKey(BackgroundImageAlignmentKey)] })
{
result._backgroundImageAlignment = ParseImageAlignment(backgroundImageAlignment.asString());
}
return result;
}
@ -654,6 +684,114 @@ std::string_view Profile::SerializeImageStretchMode(const winrt::Windows::UI::Xa
}
}
// Method Description:
// - Helper function for converting a user-specified image horizontal and vertical
// alignment to the appropriate enum values tuple
// Arguments:
// - The value from the profiles.json file
// Return Value:
// - The corresponding enum values tuple which maps to the string provided by the user
std::tuple<winrt::Windows::UI::Xaml::HorizontalAlignment, winrt::Windows::UI::Xaml::VerticalAlignment> Profile::ParseImageAlignment(const std::string_view imageAlignment)
{
if (imageAlignment == ImageAlignmentTopLeft)
{
return std::make_tuple(winrt::Windows::UI::Xaml::HorizontalAlignment::Left,
winrt::Windows::UI::Xaml::VerticalAlignment::Top);
}
else if (imageAlignment == ImageAlignmentBottomLeft)
{
return std::make_tuple(winrt::Windows::UI::Xaml::HorizontalAlignment::Left,
winrt::Windows::UI::Xaml::VerticalAlignment::Bottom);
}
else if (imageAlignment == ImageAlignmentLeft)
{
return std::make_tuple(winrt::Windows::UI::Xaml::HorizontalAlignment::Left,
winrt::Windows::UI::Xaml::VerticalAlignment::Center);
}
else if (imageAlignment == ImageAlignmentTopRight)
{
return std::make_tuple(winrt::Windows::UI::Xaml::HorizontalAlignment::Right,
winrt::Windows::UI::Xaml::VerticalAlignment::Top);
}
else if (imageAlignment == ImageAlignmentBottomRight)
{
return std::make_tuple(winrt::Windows::UI::Xaml::HorizontalAlignment::Right,
winrt::Windows::UI::Xaml::VerticalAlignment::Bottom);
}
else if (imageAlignment == ImageAlignmentRight)
{
return std::make_tuple(winrt::Windows::UI::Xaml::HorizontalAlignment::Right,
winrt::Windows::UI::Xaml::VerticalAlignment::Center);
}
else if (imageAlignment == ImageAlignmentTop)
{
return std::make_tuple(winrt::Windows::UI::Xaml::HorizontalAlignment::Center,
winrt::Windows::UI::Xaml::VerticalAlignment::Top);
}
else if (imageAlignment == ImageAlignmentBottom)
{
return std::make_tuple(winrt::Windows::UI::Xaml::HorizontalAlignment::Center,
winrt::Windows::UI::Xaml::VerticalAlignment::Bottom);
}
else // Fall through to default alignment
{
return std::make_tuple(winrt::Windows::UI::Xaml::HorizontalAlignment::Center,
winrt::Windows::UI::Xaml::VerticalAlignment::Center);
}
}
// Method Description:
// - Helper function for converting the HorizontalAlignment+VerticalAlignment tuple
// to the correct string value.
// Arguments:
// - imageAlignment: The enum values tuple to convert to a string.
// Return Value:
// - The string value for the given ImageAlignment
std::string_view Profile::SerializeImageAlignment(const std::tuple<winrt::Windows::UI::Xaml::HorizontalAlignment, winrt::Windows::UI::Xaml::VerticalAlignment> imageAlignment)
{
const auto imageHorizontalAlignment = std::get<winrt::Windows::UI::Xaml::HorizontalAlignment>(imageAlignment);
const auto imageVerticalAlignment = std::get<winrt::Windows::UI::Xaml::VerticalAlignment>(imageAlignment);
switch (imageHorizontalAlignment)
{
case winrt::Windows::UI::Xaml::HorizontalAlignment::Left:
switch (imageVerticalAlignment)
{
case winrt::Windows::UI::Xaml::VerticalAlignment::Top:
return ImageAlignmentTopLeft;
case winrt::Windows::UI::Xaml::VerticalAlignment::Bottom:
return ImageAlignmentBottomLeft;
default:
case winrt::Windows::UI::Xaml::VerticalAlignment::Center:
return ImageAlignmentLeft;
}
case winrt::Windows::UI::Xaml::HorizontalAlignment::Right:
switch (imageVerticalAlignment)
{
case winrt::Windows::UI::Xaml::VerticalAlignment::Top:
return ImageAlignmentTopRight;
case winrt::Windows::UI::Xaml::VerticalAlignment::Bottom:
return ImageAlignmentBottomRight;
default:
case winrt::Windows::UI::Xaml::VerticalAlignment::Center:
return ImageAlignmentRight;
}
default:
case winrt::Windows::UI::Xaml::HorizontalAlignment::Center:
switch (imageVerticalAlignment)
{
case winrt::Windows::UI::Xaml::VerticalAlignment::Top:
return ImageAlignmentTop;
case winrt::Windows::UI::Xaml::VerticalAlignment::Bottom:
return ImageAlignmentBottom;
default:
case winrt::Windows::UI::Xaml::VerticalAlignment::Center:
return ImageAlignmentCenter;
}
}
}
// Method Description:
// - Helper function for converting a user-specified cursor style corresponding
// CursorStyle enum value

View file

@ -62,6 +62,8 @@ private:
static winrt::Microsoft::Terminal::Settings::ScrollbarState ParseScrollbarState(const std::wstring& scrollbarState);
static winrt::Windows::UI::Xaml::Media::Stretch ParseImageStretchMode(const std::string_view imageStretchMode);
static std::string_view SerializeImageStretchMode(const winrt::Windows::UI::Xaml::Media::Stretch imageStretchMode);
static std::tuple<winrt::Windows::UI::Xaml::HorizontalAlignment, winrt::Windows::UI::Xaml::VerticalAlignment> ParseImageAlignment(const std::string_view imageAlignment);
static std::string_view SerializeImageAlignment(const std::tuple<winrt::Windows::UI::Xaml::HorizontalAlignment, winrt::Windows::UI::Xaml::VerticalAlignment> imageAlignment);
static winrt::Microsoft::Terminal::Settings::CursorStyle _ParseCursorShape(const std::wstring& cursorShapeString);
static std::wstring_view _SerializeCursorStyle(const winrt::Microsoft::Terminal::Settings::CursorStyle cursorShape);
@ -91,6 +93,7 @@ private:
std::optional<std::wstring> _backgroundImage;
std::optional<double> _backgroundImageOpacity;
std::optional<winrt::Windows::UI::Xaml::Media::Stretch> _backgroundImageStretchMode;
std::optional<std::tuple<winrt::Windows::UI::Xaml::HorizontalAlignment, winrt::Windows::UI::Xaml::VerticalAlignment>> _backgroundImageAlignment;
std::optional<std::wstring> _scrollbarState;
bool _closeOnExit;

View file

@ -276,13 +276,13 @@ namespace winrt::Microsoft::Terminal::TerminalControl::implementation
// internet.
Media::Imaging::BitmapImage image(imageUri);
_bgImageLayer.Source(image);
_bgImageLayer.HorizontalAlignment(HorizontalAlignment::Center);
_bgImageLayer.VerticalAlignment(VerticalAlignment::Center);
}
// Apply stretch and opacity settings
// Apply stretch, opacity and alignment settings
_bgImageLayer.Stretch(_settings.BackgroundImageStretchMode());
_bgImageLayer.Opacity(_settings.BackgroundImageOpacity());
_bgImageLayer.HorizontalAlignment(_settings.BackgroundImageHorizontalAlignment());
_bgImageLayer.VerticalAlignment(_settings.BackgroundImageVerticalAlignment());
}
else
{

View file

@ -37,5 +37,7 @@ namespace Microsoft.Terminal.Settings
String BackgroundImage;
Double BackgroundImageOpacity;
Windows.UI.Xaml.Media.Stretch BackgroundImageStretchMode;
Windows.UI.Xaml.HorizontalAlignment BackgroundImageHorizontalAlignment;
Windows.UI.Xaml.VerticalAlignment BackgroundImageVerticalAlignment;
};
}

View file

@ -30,6 +30,8 @@ namespace winrt::Microsoft::Terminal::Settings::implementation
_backgroundImage{},
_backgroundImageOpacity{ 1.0 },
_backgroundImageStretchMode{ winrt::Windows::UI::Xaml::Media::Stretch::UniformToFill },
_backgroundImageHorizontalAlignment{ winrt::Windows::UI::Xaml::HorizontalAlignment::Center },
_backgroundImageVerticalAlignment{ winrt::Windows::UI::Xaml::VerticalAlignment::Center },
_keyBindings{ nullptr },
_scrollbarState{ ScrollbarState::Visible }
{
@ -236,6 +238,26 @@ namespace winrt::Microsoft::Terminal::Settings::implementation
_backgroundImageStretchMode = value;
}
winrt::Windows::UI::Xaml::HorizontalAlignment TerminalSettings::BackgroundImageHorizontalAlignment()
{
return _backgroundImageHorizontalAlignment;
}
void TerminalSettings::BackgroundImageHorizontalAlignment(winrt::Windows::UI::Xaml::HorizontalAlignment value)
{
_backgroundImageHorizontalAlignment = value;
}
winrt::Windows::UI::Xaml::VerticalAlignment TerminalSettings::BackgroundImageVerticalAlignment()
{
return _backgroundImageVerticalAlignment;
}
void TerminalSettings::BackgroundImageVerticalAlignment(winrt::Windows::UI::Xaml::VerticalAlignment value)
{
_backgroundImageVerticalAlignment = value;
}
Settings::IKeyBindings TerminalSettings::KeyBindings()
{
return _keyBindings;

View file

@ -69,6 +69,10 @@ namespace winrt::Microsoft::Terminal::Settings::implementation
void BackgroundImageOpacity(double value);
winrt::Windows::UI::Xaml::Media::Stretch BackgroundImageStretchMode();
void BackgroundImageStretchMode(winrt::Windows::UI::Xaml::Media::Stretch value);
winrt::Windows::UI::Xaml::HorizontalAlignment BackgroundImageHorizontalAlignment();
void BackgroundImageHorizontalAlignment(winrt::Windows::UI::Xaml::HorizontalAlignment value);
winrt::Windows::UI::Xaml::VerticalAlignment BackgroundImageVerticalAlignment();
void BackgroundImageVerticalAlignment(winrt::Windows::UI::Xaml::VerticalAlignment value);
winrt::Microsoft::Terminal::Settings::IKeyBindings KeyBindings();
void KeyBindings(winrt::Microsoft::Terminal::Settings::IKeyBindings const& value);
@ -107,6 +111,8 @@ namespace winrt::Microsoft::Terminal::Settings::implementation
hstring _backgroundImage;
double _backgroundImageOpacity;
winrt::Windows::UI::Xaml::Media::Stretch _backgroundImageStretchMode;
winrt::Windows::UI::Xaml::HorizontalAlignment _backgroundImageHorizontalAlignment;
winrt::Windows::UI::Xaml::VerticalAlignment _backgroundImageVerticalAlignment;
hstring _commandline;
hstring _startingDir;
hstring _envVars;