mirror of
https://github.com/microsoft/terminal.git
synced 2026-04-11 16:51:00 +00:00
This pull request moves swaths of Cascadia to use `til::color` for color interop. There are still some places where we use `COLORREF`, such as in the ABI boundaries between WinRT components. I've also added two more til::color helpers - `with_alpha`, which takes an existing color and sets its alpha component, and a `Windows::UI::Color` convertor pair. Future direction might include a `TerminalSettings::Color` type at the idl boundary so we can finally stop using UInt32s (!) for color. ## Validation Steps Performed Tested certain fragile areas: * [x] setting the background with OSC 11 * [x] setting the background when acrylic is in use (which requires low-alpha)
211 lines
6.5 KiB
C++
211 lines
6.5 KiB
C++
// Copyright (c) Microsoft Corporation.
|
|
// Licensed under the MIT license.
|
|
|
|
#include "pch.h"
|
|
#include "ColorScheme.h"
|
|
#include "DefaultSettings.h"
|
|
#include "../../types/inc/Utils.hpp"
|
|
#include "Utils.h"
|
|
#include "JsonUtils.h"
|
|
|
|
using namespace ::Microsoft::Console;
|
|
using namespace TerminalApp;
|
|
using namespace winrt::Microsoft::Terminal::Settings;
|
|
using namespace winrt::Microsoft::Terminal::TerminalControl;
|
|
|
|
static constexpr std::string_view NameKey{ "name" };
|
|
static constexpr std::string_view ForegroundKey{ "foreground" };
|
|
static constexpr std::string_view BackgroundKey{ "background" };
|
|
static constexpr std::string_view SelectionBackgroundKey{ "selectionBackground" };
|
|
static constexpr std::string_view CursorColorKey{ "cursorColor" };
|
|
static constexpr std::array<std::string_view, 16> TableColors = {
|
|
"black",
|
|
"red",
|
|
"green",
|
|
"yellow",
|
|
"blue",
|
|
"purple",
|
|
"cyan",
|
|
"white",
|
|
"brightBlack",
|
|
"brightRed",
|
|
"brightGreen",
|
|
"brightYellow",
|
|
"brightBlue",
|
|
"brightPurple",
|
|
"brightCyan",
|
|
"brightWhite"
|
|
};
|
|
|
|
ColorScheme::ColorScheme() :
|
|
_schemeName{ L"" },
|
|
_table{},
|
|
_defaultForeground{ DEFAULT_FOREGROUND_WITH_ALPHA },
|
|
_defaultBackground{ DEFAULT_BACKGROUND_WITH_ALPHA },
|
|
_selectionBackground{ DEFAULT_FOREGROUND },
|
|
_cursorColor{ DEFAULT_CURSOR_COLOR }
|
|
{
|
|
}
|
|
|
|
ColorScheme::ColorScheme(std::wstring name, til::color defaultFg, til::color defaultBg, til::color cursorColor) :
|
|
_schemeName{ name },
|
|
_table{},
|
|
_defaultForeground{ defaultFg },
|
|
_defaultBackground{ defaultBg },
|
|
_selectionBackground{ DEFAULT_FOREGROUND },
|
|
_cursorColor{ cursorColor }
|
|
{
|
|
}
|
|
|
|
ColorScheme::~ColorScheme()
|
|
{
|
|
}
|
|
|
|
// Method Description:
|
|
// - Apply our values to the given TerminalSettings object. Sets the foreground,
|
|
// background, and color table of the settings object.
|
|
// Arguments:
|
|
// - terminalSettings: the object to apply our settings to.
|
|
// Return Value:
|
|
// - <none>
|
|
void ColorScheme::ApplyScheme(TerminalSettings terminalSettings) const
|
|
{
|
|
terminalSettings.DefaultForeground(static_cast<COLORREF>(_defaultForeground));
|
|
terminalSettings.DefaultBackground(static_cast<COLORREF>(_defaultBackground));
|
|
terminalSettings.SelectionBackground(static_cast<COLORREF>(_selectionBackground));
|
|
terminalSettings.CursorColor(static_cast<COLORREF>(_cursorColor));
|
|
|
|
auto const tableCount = gsl::narrow_cast<int>(_table.size());
|
|
for (int i = 0; i < tableCount; i++)
|
|
{
|
|
terminalSettings.SetColorTableEntry(i, static_cast<COLORREF>(_table[i]));
|
|
}
|
|
}
|
|
|
|
// Method Description:
|
|
// - Create a new instance of this class from a serialized JsonObject.
|
|
// Arguments:
|
|
// - json: an object which should be a serialization of a ColorScheme object.
|
|
// Return Value:
|
|
// - a new ColorScheme instance created from the values in `json`
|
|
ColorScheme ColorScheme::FromJson(const Json::Value& json)
|
|
{
|
|
ColorScheme result;
|
|
result.LayerJson(json);
|
|
return result;
|
|
}
|
|
|
|
// Method Description:
|
|
// - Returns true if we think the provided json object represents an instance of
|
|
// the same object as this object. If true, we should layer that json object
|
|
// on us, instead of creating a new object.
|
|
// Arguments:
|
|
// - json: The json object to query to see if it's the same
|
|
// Return Value:
|
|
// - true iff the json object has the same `name` as we do.
|
|
bool ColorScheme::ShouldBeLayered(const Json::Value& json) const
|
|
{
|
|
if (const auto name{ json[JsonKey(NameKey)] })
|
|
{
|
|
const auto nameFromJson = GetWstringFromJson(name);
|
|
return nameFromJson == _schemeName;
|
|
}
|
|
return false;
|
|
}
|
|
|
|
// Method Description:
|
|
// - Layer values from the given json object on top of the existing properties
|
|
// of this object. For any keys we're expecting to be able to parse in the
|
|
// given object, we'll parse them and replace our settings with values from
|
|
// the new json object. Properties that _aren't_ in the json object will _not_
|
|
// be replaced.
|
|
// Arguments:
|
|
// - json: an object which should be a partial serialization of a ColorScheme object.
|
|
// Return Value:
|
|
// <none>
|
|
void ColorScheme::LayerJson(const Json::Value& json)
|
|
{
|
|
if (auto name{ json[JsonKey(NameKey)] })
|
|
{
|
|
_schemeName = winrt::to_hstring(name.asString());
|
|
}
|
|
if (auto fgString{ json[JsonKey(ForegroundKey)] })
|
|
{
|
|
const auto color = Utils::ColorFromHexString(fgString.asString());
|
|
_defaultForeground = color;
|
|
}
|
|
if (auto bgString{ json[JsonKey(BackgroundKey)] })
|
|
{
|
|
const auto color = Utils::ColorFromHexString(bgString.asString());
|
|
_defaultBackground = color;
|
|
}
|
|
if (auto sbString{ json[JsonKey(SelectionBackgroundKey)] })
|
|
{
|
|
const auto color = Utils::ColorFromHexString(sbString.asString());
|
|
_selectionBackground = color;
|
|
}
|
|
if (auto sbString{ json[JsonKey(CursorColorKey)] })
|
|
{
|
|
const auto color = Utils::ColorFromHexString(sbString.asString());
|
|
_cursorColor = color;
|
|
}
|
|
|
|
int i = 0;
|
|
for (const auto& current : TableColors)
|
|
{
|
|
if (auto str{ json[JsonKey(current)] })
|
|
{
|
|
const auto color = Utils::ColorFromHexString(str.asString());
|
|
_table.at(i) = color;
|
|
}
|
|
i++;
|
|
}
|
|
}
|
|
|
|
std::wstring_view ColorScheme::GetName() const noexcept
|
|
{
|
|
return { _schemeName };
|
|
}
|
|
|
|
std::array<til::color, COLOR_TABLE_SIZE>& ColorScheme::GetTable() noexcept
|
|
{
|
|
return _table;
|
|
}
|
|
|
|
til::color ColorScheme::GetForeground() const noexcept
|
|
{
|
|
return _defaultForeground;
|
|
}
|
|
|
|
til::color ColorScheme::GetBackground() const noexcept
|
|
{
|
|
return _defaultBackground;
|
|
}
|
|
|
|
til::color ColorScheme::GetSelectionBackground() const noexcept
|
|
{
|
|
return _selectionBackground;
|
|
}
|
|
|
|
til::color ColorScheme::GetCursorColor() const noexcept
|
|
{
|
|
return _cursorColor;
|
|
}
|
|
|
|
// Method Description:
|
|
// - Parse the name from the JSON representation of a ColorScheme.
|
|
// Arguments:
|
|
// - json: an object which should be a serialization of a ColorScheme object.
|
|
// Return Value:
|
|
// - the name of the color scheme represented by `json` as a std::wstring optional
|
|
// i.e. the value of the `name` property.
|
|
// - returns std::nullopt if `json` doesn't have the `name` property
|
|
std::optional<std::wstring> TerminalApp::ColorScheme::GetNameFromJson(const Json::Value& json)
|
|
{
|
|
if (const auto name{ json[JsonKey(NameKey)] })
|
|
{
|
|
return GetWstringFromJson(name);
|
|
}
|
|
return std::nullopt;
|
|
}
|