Gui: StyleParameters - use Base::Color instead of QColor
If possible we should prefer using our own classess instead of ones coming from frameworks. This changes Style Parameters to use Base::Color class instead of QColor. Calculations are still done using QColor but the data is always exposed as Base::Color.
This commit is contained in:
@@ -30,6 +30,7 @@
|
||||
#include "ui_DlgThemeEditor.h"
|
||||
#include "BitmapFactory.h"
|
||||
|
||||
#include <Utilities.h>
|
||||
#include <Base/ServiceProvider.h>
|
||||
#include <Base/Tools.h>
|
||||
|
||||
@@ -67,7 +68,7 @@ QString typeOfTokenValue(const Gui::StyleParameters::Value& value)
|
||||
[](const Gui::StyleParameters::Length&) {
|
||||
return QWidget::tr("Length");
|
||||
},
|
||||
[](const QColor&) {
|
||||
[](const Base::Color&) {
|
||||
return QWidget::tr("Color");
|
||||
}
|
||||
},
|
||||
@@ -529,8 +530,8 @@ QVariant StyleParametersModel::data(const QModelIndex& index, int role) const
|
||||
}
|
||||
|
||||
if (role == Qt::DecorationRole) {
|
||||
if (index.column() == ParameterPreview && std::holds_alternative<QColor>(value)) {
|
||||
return colorPreview(std::get<QColor>(value));
|
||||
if (index.column() == ParameterPreview && std::holds_alternative<Base::Color>(value)) {
|
||||
return colorPreview(std::get<Base::Color>(value).asValue<QColor>());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -95,9 +95,9 @@ std::string Value::toString() const
|
||||
return fmt::format("{}{}", value, unit);
|
||||
}
|
||||
|
||||
if (std::holds_alternative<QColor>(*this)) {
|
||||
auto color = std::get<QColor>(*this);
|
||||
return fmt::format("#{:0>6x}", 0xFFFFFF & color.rgb()); // NOLINT(*-magic-numbers)
|
||||
if (std::holds_alternative<Base::Color>(*this)) {
|
||||
auto color = std::get<Base::Color>(*this);
|
||||
return fmt::format("#{:0>6x}", color.getPackedRGB() >> 8); // NOLINT(*-magic-numbers)
|
||||
}
|
||||
|
||||
return std::get<std::string>(*this);
|
||||
|
||||
@@ -107,9 +107,9 @@ private:
|
||||
*
|
||||
* As a rule, operations can be only performed over values of the same type.
|
||||
*/
|
||||
struct Value : std::variant<Length, QColor, std::string>
|
||||
struct Value : std::variant<Numeric, Base::Color, std::string>
|
||||
{
|
||||
using std::variant<Length, QColor, std::string>::variant;
|
||||
using std::variant<Numeric, Base::Color, std::string>::variant;
|
||||
|
||||
/**
|
||||
* Converts the object into its string representation.
|
||||
|
||||
@@ -26,6 +26,7 @@
|
||||
#include "Parser.h"
|
||||
#include "ParameterManager.h"
|
||||
|
||||
#include <Utilities.h>
|
||||
#include <Base/Tools.h>
|
||||
|
||||
#ifndef _PreComp_
|
||||
@@ -67,12 +68,12 @@ Value FunctionCall::evaluate(const EvaluationContext& context) const
|
||||
auto colorArg = arguments[0]->evaluate(context);
|
||||
auto amountArg = arguments[1]->evaluate(context);
|
||||
|
||||
if (!std::holds_alternative<QColor>(colorArg)) {
|
||||
if (!std::holds_alternative<Base::Color>(colorArg)) {
|
||||
THROWM(Base::ExpressionError,
|
||||
fmt::format("'{}' is not supported for colors", functionName));
|
||||
}
|
||||
|
||||
auto color = std::get<QColor>(colorArg);
|
||||
auto color = std::get<Base::Color>(colorArg).asValue<QColor>();
|
||||
|
||||
// In Qt if you want to make color 20% darker or lighter, you need to pass 120 as the value
|
||||
// we, however, want users to pass only the relative difference, hence we need to add the
|
||||
@@ -82,11 +83,11 @@ Value FunctionCall::evaluate(const EvaluationContext& context) const
|
||||
auto amount = 100 + static_cast<int>(std::get<Length>(amountArg).value);
|
||||
|
||||
if (functionName == "lighten") {
|
||||
return color.lighter(amount);
|
||||
return Base::Color::fromValue(color.lighter(amount));
|
||||
}
|
||||
|
||||
if (functionName == "darken") {
|
||||
return color.darker(amount);
|
||||
return Base::Color::fromValue(color.darker(amount));
|
||||
}
|
||||
|
||||
return {};
|
||||
@@ -104,25 +105,25 @@ Value FunctionCall::evaluate(const EvaluationContext& context) const
|
||||
auto secondColorArg = arguments[1]->evaluate(context);
|
||||
auto amountArg = arguments[2]->evaluate(context);
|
||||
|
||||
if (!std::holds_alternative<QColor>(firstColorArg)) {
|
||||
if (!std::holds_alternative<Base::Color>(firstColorArg)) {
|
||||
THROWM(Base::ExpressionError,
|
||||
fmt::format("first argument of '{}' must be color", functionName));
|
||||
}
|
||||
|
||||
if (!std::holds_alternative<QColor>(secondColorArg)) {
|
||||
if (!std::holds_alternative<Base::Color>(secondColorArg)) {
|
||||
THROWM(Base::ExpressionError,
|
||||
fmt::format("second argument of '{}' must be color", functionName));
|
||||
}
|
||||
|
||||
auto firstColor = std::get<QColor>(firstColorArg);
|
||||
auto secondColor = std::get<QColor>(secondColorArg);
|
||||
auto firstColor = std::get<Base::Color>(firstColorArg);
|
||||
auto secondColor = std::get<Base::Color>(secondColorArg);
|
||||
|
||||
auto amount = Base::fromPercent(std::get<Length>(amountArg).value);
|
||||
auto amount = Base::fromPercent(static_cast<long>(std::get<Length>(amountArg).value));
|
||||
|
||||
return QColor::fromRgbF(
|
||||
(1 - amount) * firstColor.redF() + amount * secondColor.redF(),
|
||||
(1 - amount) * firstColor.greenF() + amount * secondColor.greenF(),
|
||||
(1 - amount) * firstColor.blueF() + amount * secondColor.blueF()
|
||||
return Base::Color(
|
||||
(1 - amount) * firstColor.r + amount * secondColor.r,
|
||||
(1 - amount) * firstColor.g + amount * secondColor.g,
|
||||
(1 - amount) * firstColor.b + amount * secondColor.b
|
||||
);
|
||||
};
|
||||
|
||||
@@ -169,7 +170,7 @@ Value BinaryOp::evaluate(const EvaluationContext& context) const
|
||||
Value UnaryOp::evaluate(const EvaluationContext& context) const
|
||||
{
|
||||
Value val = operand->evaluate(context);
|
||||
if (std::holds_alternative<QColor>(val)) {
|
||||
if (std::holds_alternative<Base::Color>(val)) {
|
||||
THROWM(Base::ExpressionError, "Unary operations on colors are not supported");
|
||||
}
|
||||
|
||||
@@ -286,7 +287,7 @@ std::unique_ptr<Expr> Parser::parseColor()
|
||||
int b = std::stoi(input.substr(pos, 2), nullptr, hexadecimalBase);
|
||||
pos += 2;
|
||||
|
||||
return std::make_unique<Color>(QColor(r, g, b));
|
||||
return std::make_unique<Color>(Base::Color(r / 255.0, g / 255.0, b / 255.0));
|
||||
};
|
||||
|
||||
const auto parseFunctionStyleColor = [&]() {
|
||||
@@ -313,7 +314,7 @@ std::unique_ptr<Expr> Parser::parseColor()
|
||||
if (!match(')')) {
|
||||
THROWM(Base::ParserError, fmt::format("Expected ')' after color arguments, got '{}'", input[pos]));
|
||||
}
|
||||
return std::make_unique<Color>(QColor(r, g, b, a));
|
||||
return std::make_unique<Color>(Base::Color(r / 255.0, g / 255.0, b / 255.0, a / 255.0));
|
||||
};
|
||||
|
||||
skipWhitespace();
|
||||
|
||||
@@ -83,9 +83,9 @@ struct GuiExport Number: public Expr
|
||||
|
||||
struct GuiExport Color: public Expr
|
||||
{
|
||||
QColor color;
|
||||
Base::Color color;
|
||||
|
||||
explicit Color(QColor color)
|
||||
explicit Color(Base::Color color)
|
||||
: color(std::move(color))
|
||||
{}
|
||||
|
||||
|
||||
@@ -24,6 +24,7 @@
|
||||
#include <gtest/gtest.h>
|
||||
|
||||
#include <Gui/Application.h>
|
||||
#include <Gui/Utilities.h>
|
||||
#include <Gui/StyleParameters/ParameterManager.h>
|
||||
|
||||
using namespace Gui::StyleParameters;
|
||||
@@ -73,20 +74,20 @@ TEST_F(ParameterManagerTest, BasicParameterResolution)
|
||||
|
||||
{
|
||||
auto result = manager.resolve("PrimaryColor");
|
||||
EXPECT_TRUE(std::holds_alternative<QColor>(result));
|
||||
auto color = std::get<QColor>(result);
|
||||
EXPECT_EQ(color.red(), 255);
|
||||
EXPECT_EQ(color.green(), 0);
|
||||
EXPECT_EQ(color.blue(), 0);
|
||||
EXPECT_TRUE(std::holds_alternative<Base::Color>(result));
|
||||
auto color = std::get<Base::Color>(result);
|
||||
EXPECT_EQ(color.r, 1);
|
||||
EXPECT_EQ(color.g, 0);
|
||||
EXPECT_EQ(color.b, 0);
|
||||
}
|
||||
|
||||
{
|
||||
auto result = manager.resolve("SecondaryColor");
|
||||
EXPECT_TRUE(std::holds_alternative<QColor>(result));
|
||||
auto color = std::get<QColor>(result);
|
||||
EXPECT_EQ(color.red(), 0);
|
||||
EXPECT_EQ(color.green(), 255);
|
||||
EXPECT_EQ(color.blue(), 0);
|
||||
EXPECT_TRUE(std::holds_alternative<Base::Color>(result));
|
||||
auto color = std::get<Base::Color>(result);
|
||||
EXPECT_EQ(color.r, 0);
|
||||
EXPECT_EQ(color.g, 1);
|
||||
EXPECT_EQ(color.b, 0);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -294,10 +295,10 @@ TEST_F(ParameterManagerTest, ComplexExpressions)
|
||||
|
||||
{
|
||||
auto result = manager.resolve("ColorWithFunction");
|
||||
EXPECT_TRUE(std::holds_alternative<QColor>(result));
|
||||
auto color = std::get<QColor>(result);
|
||||
EXPECT_TRUE(std::holds_alternative<Base::Color>(result));
|
||||
auto color = std::get<Base::Color>(result).asValue<QColor>();
|
||||
// Should be lighter than the original red
|
||||
EXPECT_GT(color.lightness(), QColor("#ff0000").lightness());
|
||||
EXPECT_GT(color.lightness(), QColor(0xff0000).lightness());
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -23,7 +23,7 @@
|
||||
|
||||
#include <gtest/gtest.h>
|
||||
|
||||
#include <QColor>
|
||||
#include <Gui/Utilities.h>
|
||||
|
||||
#include <Gui/StyleParameters/Parser.h>
|
||||
#include <Gui/StyleParameters/ParameterManager.h>
|
||||
@@ -103,56 +103,56 @@ TEST_F(ParserTest, ParseColors)
|
||||
Parser parser("#ff0000");
|
||||
auto expr = parser.parse();
|
||||
auto result = expr->evaluate({&manager, {}});
|
||||
EXPECT_TRUE(std::holds_alternative<QColor>(result));
|
||||
auto color = std::get<QColor>(result);
|
||||
EXPECT_EQ(color.red(), 255);
|
||||
EXPECT_EQ(color.green(), 0);
|
||||
EXPECT_EQ(color.blue(), 0);
|
||||
EXPECT_TRUE(std::holds_alternative<Base::Color>(result));
|
||||
auto color = std::get<Base::Color>(result);
|
||||
EXPECT_EQ(color.r, 1);
|
||||
EXPECT_EQ(color.g, 0);
|
||||
EXPECT_EQ(color.b, 0);
|
||||
}
|
||||
|
||||
{
|
||||
Parser parser("#00ff00");
|
||||
auto expr = parser.parse();
|
||||
auto result = expr->evaluate({&manager, {}});
|
||||
EXPECT_TRUE(std::holds_alternative<QColor>(result));
|
||||
auto color = std::get<QColor>(result);
|
||||
EXPECT_EQ(color.red(), 0);
|
||||
EXPECT_EQ(color.green(), 255);
|
||||
EXPECT_EQ(color.blue(), 0);
|
||||
EXPECT_TRUE(std::holds_alternative<Base::Color>(result));
|
||||
auto color = std::get<Base::Color>(result);
|
||||
EXPECT_EQ(color.r, 0);
|
||||
EXPECT_EQ(color.g, 1);
|
||||
EXPECT_EQ(color.b, 0);
|
||||
}
|
||||
|
||||
{
|
||||
Parser parser("#0000ff");
|
||||
auto expr = parser.parse();
|
||||
auto result = expr->evaluate({&manager, {}});
|
||||
EXPECT_TRUE(std::holds_alternative<QColor>(result));
|
||||
auto color = std::get<QColor>(result);
|
||||
EXPECT_EQ(color.red(), 0);
|
||||
EXPECT_EQ(color.green(), 0);
|
||||
EXPECT_EQ(color.blue(), 255);
|
||||
EXPECT_TRUE(std::holds_alternative<Base::Color>(result));
|
||||
auto color = std::get<Base::Color>(result);
|
||||
EXPECT_EQ(color.r, 0);
|
||||
EXPECT_EQ(color.g, 0);
|
||||
EXPECT_EQ(color.b, 1);
|
||||
}
|
||||
|
||||
{
|
||||
Parser parser("rgb(255, 0, 0)");
|
||||
auto expr = parser.parse();
|
||||
auto result = expr->evaluate({&manager, {}});
|
||||
EXPECT_TRUE(std::holds_alternative<QColor>(result));
|
||||
auto color = std::get<QColor>(result);
|
||||
EXPECT_EQ(color.red(), 255);
|
||||
EXPECT_EQ(color.green(), 0);
|
||||
EXPECT_EQ(color.blue(), 0);
|
||||
EXPECT_TRUE(std::holds_alternative<Base::Color>(result));
|
||||
auto color = std::get<Base::Color>(result);
|
||||
EXPECT_EQ(color.r, 1);
|
||||
EXPECT_EQ(color.g, 0);
|
||||
EXPECT_EQ(color.b, 0);
|
||||
}
|
||||
|
||||
{
|
||||
Parser parser("rgba(255, 0, 0, 128)");
|
||||
auto expr = parser.parse();
|
||||
auto result = expr->evaluate({&manager, {}});
|
||||
EXPECT_TRUE(std::holds_alternative<QColor>(result));
|
||||
auto color = std::get<QColor>(result);
|
||||
EXPECT_EQ(color.red(), 255);
|
||||
EXPECT_EQ(color.green(), 0);
|
||||
EXPECT_EQ(color.blue(), 0);
|
||||
EXPECT_EQ(color.alpha(), 128);
|
||||
EXPECT_TRUE(std::holds_alternative<Base::Color>(result));
|
||||
auto color = std::get<Base::Color>(result);
|
||||
EXPECT_DOUBLE_EQ(color.r, 1);
|
||||
EXPECT_DOUBLE_EQ(color.g, 0);
|
||||
EXPECT_DOUBLE_EQ(color.b, 0);
|
||||
EXPECT_NEAR(color.a, 128 / 255.0, 1e-6);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -173,11 +173,11 @@ TEST_F(ParserTest, ParseParameterReferences)
|
||||
Parser parser("@TestColor");
|
||||
auto expr = parser.parse();
|
||||
auto result = expr->evaluate({.manager = &manager, .context = {}});
|
||||
EXPECT_TRUE(std::holds_alternative<QColor>(result));
|
||||
auto color = std::get<QColor>(result);
|
||||
EXPECT_EQ(color.red(), 255);
|
||||
EXPECT_EQ(color.green(), 0);
|
||||
EXPECT_EQ(color.blue(), 0);
|
||||
EXPECT_TRUE(std::holds_alternative<Base::Color>(result));
|
||||
auto color = std::get<Base::Color>(result);
|
||||
EXPECT_EQ(color.r, 1);
|
||||
EXPECT_EQ(color.g, 0);
|
||||
EXPECT_EQ(color.b, 0);
|
||||
}
|
||||
|
||||
{
|
||||
@@ -360,30 +360,30 @@ TEST_F(ParserTest, ParseFunctionCalls)
|
||||
Parser parser("lighten(#ff0000, 20)");
|
||||
auto expr = parser.parse();
|
||||
auto result = expr->evaluate({&manager, {}});
|
||||
EXPECT_TRUE(std::holds_alternative<QColor>(result));
|
||||
auto color = std::get<QColor>(result);
|
||||
EXPECT_TRUE(std::holds_alternative<Base::Color>(result));
|
||||
auto color = std::get<Base::Color>(result).asValue<QColor>();
|
||||
// The result should be lighter than the original red
|
||||
EXPECT_GT(color.lightness(), QColor("#ff0000").lightness());
|
||||
EXPECT_GT(color.lightness(), QColor(0xff0000).lightness());
|
||||
}
|
||||
|
||||
{
|
||||
Parser parser("darken(#ff0000, 20)");
|
||||
auto expr = parser.parse();
|
||||
auto result = expr->evaluate({&manager, {}});
|
||||
EXPECT_TRUE(std::holds_alternative<QColor>(result));
|
||||
auto color = std::get<QColor>(result);
|
||||
EXPECT_TRUE(std::holds_alternative<Base::Color>(result));
|
||||
auto color = std::get<Base::Color>(result).asValue<QColor>();
|
||||
// The result should be darker than the original red
|
||||
EXPECT_LT(color.lightness(), QColor("#ff0000").lightness());
|
||||
EXPECT_LT(color.lightness(), QColor(0xff0000).lightness());
|
||||
}
|
||||
|
||||
{
|
||||
Parser parser("lighten(@TestColor, 20)");
|
||||
auto expr = parser.parse();
|
||||
auto result = expr->evaluate({&manager, {}});
|
||||
EXPECT_TRUE(std::holds_alternative<QColor>(result));
|
||||
auto color = std::get<QColor>(result);
|
||||
EXPECT_TRUE(std::holds_alternative<Base::Color>(result));
|
||||
auto color = std::get<Base::Color>(result).asValue<QColor>();
|
||||
// The result should be lighter than the original red
|
||||
EXPECT_GT(color.lightness(), QColor("#ff0000").lightness());
|
||||
EXPECT_GT(color.lightness(), QColor(0xff0000).lightness());
|
||||
}
|
||||
}
|
||||
|
||||
@@ -496,11 +496,11 @@ TEST_F(ParserTest, ParseWhitespace)
|
||||
Parser parser("rgb(255,0,0)");
|
||||
auto expr = parser.parse();
|
||||
auto result = expr->evaluate({&manager, {}});
|
||||
EXPECT_TRUE(std::holds_alternative<QColor>(result));
|
||||
auto color = std::get<QColor>(result);
|
||||
EXPECT_EQ(color.red(), 255);
|
||||
EXPECT_EQ(color.green(), 0);
|
||||
EXPECT_EQ(color.blue(), 0);
|
||||
EXPECT_TRUE(std::holds_alternative<Base::Color>(result));
|
||||
auto color = std::get<Base::Color>(result);
|
||||
EXPECT_EQ(color.r, 1);
|
||||
EXPECT_EQ(color.g, 0);
|
||||
EXPECT_EQ(color.b, 0);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -539,11 +539,11 @@ TEST_F(ParserTest, ParseEdgeCases)
|
||||
Parser parser("#ff0000");
|
||||
auto expr = parser.parse();
|
||||
auto result = expr->evaluate({&manager, {}});
|
||||
EXPECT_TRUE(std::holds_alternative<QColor>(result));
|
||||
auto color = std::get<QColor>(result);
|
||||
EXPECT_EQ(color.red(), 255);
|
||||
EXPECT_EQ(color.green(), 0);
|
||||
EXPECT_EQ(color.blue(), 0);
|
||||
EXPECT_TRUE(std::holds_alternative<Base::Color>(result));
|
||||
auto color = std::get<Base::Color>(result);
|
||||
EXPECT_EQ(color.r, 1);
|
||||
EXPECT_EQ(color.g, 0);
|
||||
EXPECT_EQ(color.b, 0);
|
||||
}
|
||||
|
||||
// Single parameter reference
|
||||
|
||||
Reference in New Issue
Block a user