Repository: microsoft/terminal
File: src/cascadia/TerminalSettingsModel/AppearanceConfig.cpp (C++)

Code before:
// 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.
// - Optional values that are set to `null` in the json object
//   will be set to nullopt.
// - This is similar to Profile::LayerJson but for AppearanceConfig
// Arguments:
// - json: an object which should be a partial serialization of an AppearanceConfig object.
void AppearanceConfig::LayerJson(const Json::Value& json)
{
    JsonUtils::GetValueForKey(json, ForegroundKey, _Foreground);
    JsonUtils::GetValueForKey(json, BackgroundKey, _Background);
    JsonUtils::GetValueForKey(json, SelectionBackgroundKey, _SelectionBackground);
    JsonUtils::GetValueForKey(json, CursorColorKey, _CursorColor);

    JsonUtils::GetValueForKey(json, LegacyAcrylicTransparencyKey, _Opacity);
    JsonUtils::GetValueForKey(json, OpacityKey, _Opacity, JsonUtils::OptionalConverter<double, IntAsFloatPercentConversionTrait>{});
    if (json["colorScheme"].isString())
    {
        // to make the UI happy, set ColorSchemeName.
        JsonUtils::GetValueForKey(json, ColorSchemeKey, _ColorSchemeName);
        JsonUtils::GetValueForKey(json, ColorSchemeKey, _DarkColorSchemeName);
        JsonUtils::GetValueForKey(json, ColorSchemeKey, _LightColorSchemeName);
    }
    else if (json["colorScheme"].isObject())
    {
        // to make the UI happy, set ColorSchemeName to whatever the dark value is.
        JsonUtils::GetValueForKey(json["colorScheme"], "dark", _ColorSchemeName);
        JsonUtils::GetValueForKey(json["colorScheme"], "dark", _DarkColorSchemeName);
        JsonUtils::GetValueForKey(json["colorScheme"], "light", _LightColorSchemeName);
    }

#define APPEARANCE_SETTINGS_LAYER_JSON(type, name, jsonKey, ...) \
    JsonUtils::GetValueForKey(json, jsonKey, _##name);
    MTSM_APPEARANCE_SETTINGS(APPEARANCE_SETTINGS_LAYER_JSON)
#undef APPEARANCE_SETTINGS_LAYER_JSON
}

winrt::Microsoft::Terminal::Settings::Model::Profile AppearanceConfig::SourceProfile()
{
    return _sourceProfile.get();
}

// Method Description:
// - Returns this AppearanceConfig's background image path, if one is set, expanding
//   any environment variables in the path, if there are any.
// - Or if "DesktopWallpaper" is set, then gets the path to the desktops wallpaper.
// - This is the same as Profile::ExpandedBackgroundImagePath, but for AppearanceConfig

Review comment (suggestion):
This way you can avoid deserializing the same JSON repeatedly:
```suggestion
        JsonUtils::GetValueForKey(json, ColorSchemeKey, _ColorSchemeName);
        _DarkColorSchemeName = _ColorSchemeName;
        _LightColorSchemeName = _ColorSchemeName;
```

Code after:
// - Optional values that are set to `null` in the json object
//   will be set to nullopt.
// - This is similar to Profile::LayerJson but for AppearanceConfig
// Arguments:
// - json: an object which should be a partial serialization of an AppearanceConfig object.
void AppearanceConfig::LayerJson(const Json::Value& json)
{
    JsonUtils::GetValueForKey(json, ForegroundKey, _Foreground);
    JsonUtils::GetValueForKey(json, BackgroundKey, _Background);
    JsonUtils::GetValueForKey(json, SelectionBackgroundKey, _SelectionBackground);
    JsonUtils::GetValueForKey(json, CursorColorKey, _CursorColor);

    JsonUtils::GetValueForKey(json, LegacyAcrylicTransparencyKey, _Opacity);
    JsonUtils::GetValueForKey(json, OpacityKey, _Opacity, JsonUtils::OptionalConverter<double, IntAsFloatPercentConversionTrait>{});
    if (json["colorScheme"].isString())
    {
        // to make the UI happy, set ColorSchemeName.
        JsonUtils::GetValueForKey(json, ColorSchemeKey, _DarkColorSchemeName);
        _LightColorSchemeName = _DarkColorSchemeName;
    }
    else if (json["colorScheme"].isObject())
    {
        // to make the UI happy, set ColorSchemeName to whatever the dark value is.
        JsonUtils::GetValueForKey(json["colorScheme"], "dark", _DarkColorSchemeName);
        JsonUtils::GetValueForKey(json["colorScheme"], "light", _LightColorSchemeName);
    }

#define APPEARANCE_SETTINGS_LAYER_JSON(type, name, jsonKey, ...) \
    JsonUtils::GetValueForKey(json, jsonKey, _##name);
    MTSM_APPEARANCE_SETTINGS(APPEARANCE_SETTINGS_LAYER_JSON)
#undef APPEARANCE_SETTINGS_LAYER_JSON
}

winrt::Microsoft::Terminal::Settings::Model::Profile AppearanceConfig::SourceProfile()
{
    return _sourceProfile.get();
}

// Method Description:
// - Returns this AppearanceConfig's background image path, if one is set, expanding
//   any environment variables in the path, if there are any.
// - Or if "DesktopWallpaper" is set, then gets the path to the desktops wallpaper.
// - This is the same as Profile::ExpandedBackgroundImagePath, but for AppearanceConfig
// - NOTE: This is just placeholder for now, eventually the path will no longer be expanded in the settings model
// Return Value:
// - This profile's expanded background image path / desktops's wallpaper path /the empty string.
winrt::hstring AppearanceConfig::ExpandedBackgroundImagePath()
{
    const auto path{ BackgroundImagePath() };
    if (path.empty())
    {