[editor] 为LayerStyleContainer重载了<<运算符 | #30
parent
ba4be72918
commit
2f9b988dac
|
@ -92,9 +92,9 @@ void LayerStyleContainer::computeNewHash()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
LayerStyleContainer LayerStyleContainer::fromJson(bool isClosedElement, const QJsonArray& jsonArray)
|
LayerStyleContainer LayerStyleContainer::fromJson(ElementType elementType, const QJsonArray& jsonArray)
|
||||||
{
|
{
|
||||||
LayerStyleContainer container(isClosedElement);
|
LayerStyleContainer container(elementType);
|
||||||
for (const auto& style : jsonArray)
|
for (const auto& style : jsonArray)
|
||||||
{
|
{
|
||||||
container.useStyle(LayerStyle::fromJson(style.toObject()));
|
container.useStyle(LayerStyle::fromJson(style.toObject()));
|
||||||
|
@ -102,20 +102,20 @@ LayerStyleContainer LayerStyleContainer::fromJson(bool isClosedElement, const QJ
|
||||||
return container;
|
return container;
|
||||||
}
|
}
|
||||||
|
|
||||||
LayerStyleContainer::LayerStyleContainer(bool isClosedElement) : hash(0)
|
LayerStyleContainer::LayerStyleContainer(ElementType elementType) : hash(0)
|
||||||
{
|
{
|
||||||
for (const auto& style : commonStyles)
|
for (const auto& style : commonStyles)
|
||||||
{
|
{
|
||||||
unusedStyles.insert(style);
|
unusedStyles.insert(style);
|
||||||
}
|
}
|
||||||
if (isClosedElement)
|
if (elementType & LayerStyleContainer::TYPE_CLOSED)
|
||||||
{
|
{
|
||||||
for (const auto& style : closedOnlyStyles)
|
for (const auto& style : closedOnlyStyles)
|
||||||
{
|
{
|
||||||
unusedStyles.insert(style);
|
unusedStyles.insert(style);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else
|
if (elementType & LayerStyleContainer::TYPE_UNCLOSED)
|
||||||
{
|
{
|
||||||
for (const auto& style : unclosedOnlyStyles)
|
for (const auto& style : unclosedOnlyStyles)
|
||||||
{
|
{
|
||||||
|
@ -182,13 +182,29 @@ std::map<QString, std::shared_ptr<LayerStyle>>::iterator LayerStyleContainer::en
|
||||||
return styles.end();
|
return styles.end();
|
||||||
}
|
}
|
||||||
|
|
||||||
bool LayerStyleContainer::useStyle(const std::shared_ptr<LayerStyle>& style)
|
std::map<QString, std::shared_ptr<LayerStyle>>::const_iterator LayerStyleContainer::cbegin() const
|
||||||
{
|
{
|
||||||
auto styleNode = unusedStyles.extract(style->getDisplayName());
|
return styles.cbegin();
|
||||||
|
}
|
||||||
|
|
||||||
|
std::map<QString, std::shared_ptr<LayerStyle>>::const_iterator LayerStyleContainer::cend() const
|
||||||
|
{
|
||||||
|
return styles.cend();
|
||||||
|
}
|
||||||
|
|
||||||
|
bool LayerStyleContainer::useStyle(const std::shared_ptr<LayerStyle>& style, bool forceOverride)
|
||||||
|
{
|
||||||
|
const auto styleDisplayName = style->getDisplayName();
|
||||||
|
auto styleNode = unusedStyles.extract(styleDisplayName);
|
||||||
if (styleNode.empty())
|
if (styleNode.empty())
|
||||||
|
{
|
||||||
|
if (!forceOverride || !styles.contains(styleDisplayName))
|
||||||
{
|
{
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
styles[styleDisplayName] = style;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
styles[styleNode.key()] = style;
|
styles[styleNode.key()] = style;
|
||||||
usedStyles.insert(std::move(styleNode));
|
usedStyles.insert(std::move(styleNode));
|
||||||
return true;
|
return true;
|
||||||
|
@ -259,6 +275,18 @@ bool LayerStyleContainer::operator==(const LayerStyleContainer& other) const
|
||||||
return std::ranges::equal(styles | std::views::values, other.styles | std::views::values);
|
return std::ranges::equal(styles | std::views::values, other.styles | std::views::values);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
LayerStyleContainer LayerStyleContainer::operator<<(const LayerStyleContainer& other) const
|
||||||
|
{
|
||||||
|
LayerStyleContainer result = other;
|
||||||
|
for (const auto& style : std::ranges::subrange(this->cbegin(), this->cend())
|
||||||
|
| std::views::values)
|
||||||
|
{
|
||||||
|
result.useStyle(style);
|
||||||
|
}
|
||||||
|
result.computeNewHash();
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
std::unique_ptr<StrokeElementLayerStyle> StrokeElementLayerStyle::fromJson(const QJsonObject& json)
|
std::unique_ptr<StrokeElementLayerStyle> StrokeElementLayerStyle::fromJson(const QJsonObject& json)
|
||||||
{
|
{
|
||||||
auto ptr = std::make_unique<StrokeElementLayerStyle>(
|
auto ptr = std::make_unique<StrokeElementLayerStyle>(
|
||||||
|
|
|
@ -116,27 +116,35 @@ private:
|
||||||
std::map<QString, std::shared_ptr<LayerStyle>> styles;
|
std::map<QString, std::shared_ptr<LayerStyle>> styles;
|
||||||
size_t hash;
|
size_t hash;
|
||||||
public:
|
public:
|
||||||
static LayerStyleContainer fromJson(bool isClosedElement, const QJsonArray& jsonArray);
|
using ElementType = unsigned short;
|
||||||
|
constexpr static ElementType TYPE_ALL = 0xffff;
|
||||||
|
constexpr static ElementType TYPE_CLOSED = 0b01;
|
||||||
|
constexpr static ElementType TYPE_UNCLOSED = 0b10;
|
||||||
|
|
||||||
LayerStyleContainer(bool isClosedElement);
|
static LayerStyleContainer fromJson(ElementType elementType, const QJsonArray& jsonArray);
|
||||||
std::vector<Renderer::BaseStyle> toBaseStyles() const override;
|
|
||||||
QJsonArray toJson() const;
|
|
||||||
|
|
||||||
bool empty() const;
|
LayerStyleContainer(ElementType elementType);
|
||||||
bool full() const;
|
[[nodiscard]] std::vector<Renderer::BaseStyle> toBaseStyles() const override;
|
||||||
std::map<QString, std::shared_ptr<LayerStyle>>::iterator begin();
|
[[nodiscard]] QJsonArray toJson() const;
|
||||||
std::map<QString, std::shared_ptr<LayerStyle>>::iterator end();
|
|
||||||
|
|
||||||
QStringList unusedStyleNames() const;
|
[[nodiscard]] bool empty() const;
|
||||||
std::unique_ptr<LayerStyle> makeUnusedStyle(const QString& styleName) const;
|
[[nodiscard]] bool full() const;
|
||||||
bool useStyle(const std::shared_ptr<LayerStyle>& style);
|
[[nodiscard]] std::map<QString, std::shared_ptr<LayerStyle>>::iterator begin();
|
||||||
|
[[nodiscard]] std::map<QString, std::shared_ptr<LayerStyle>>::iterator end();
|
||||||
|
[[nodiscard]] std::map<QString, std::shared_ptr<LayerStyle>>::const_iterator cbegin() const;
|
||||||
|
[[nodiscard]] std::map<QString, std::shared_ptr<LayerStyle>>::const_iterator cend() const;
|
||||||
|
|
||||||
|
[[nodiscard]] QStringList unusedStyleNames() const;
|
||||||
|
[[nodiscard]] std::unique_ptr<LayerStyle> makeUnusedStyle(const QString& styleName) const;
|
||||||
|
bool useStyle(const std::shared_ptr<LayerStyle>& style, bool forceOverride = false);
|
||||||
bool overrideStyle(const std::shared_ptr<LayerStyle>& style);
|
bool overrideStyle(const std::shared_ptr<LayerStyle>& style);
|
||||||
bool dropStyle(const QString& styleName);
|
bool dropStyle(const QString& styleName);
|
||||||
std::shared_ptr<LayerStyle> getStyle(const QString& styleName) const;
|
[[nodiscard]] std::shared_ptr<LayerStyle> getStyle(const QString& styleName) const;
|
||||||
float boundingBoxAffectValue() const;
|
[[nodiscard]] float boundingBoxAffectValue() const;
|
||||||
size_t getHash() const;
|
[[nodiscard]] size_t getHash() const;
|
||||||
|
|
||||||
bool operator==(const LayerStyleContainer& other) const;
|
[[nodiscard]] bool operator==(const LayerStyleContainer& other) const;
|
||||||
|
[[nodiscard]] LayerStyleContainer operator<<(const LayerStyleContainer& other) const;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 需要在每次更改后手动调用
|
* 需要在每次更改后手动调用
|
||||||
|
|
|
@ -79,7 +79,9 @@ FolderLayerWrapper::FolderLayerWrapper(QJsonObject json, ElementManager *element
|
||||||
LeafLayerWrapper::LeafLayerWrapper(QJsonObject json, ElementManager* elementManager, FolderLayerWrapper* parent)
|
LeafLayerWrapper::LeafLayerWrapper(QJsonObject json, ElementManager* elementManager, FolderLayerWrapper* parent)
|
||||||
: LayerWrapper(json, parent, elementManager),
|
: LayerWrapper(json, parent, elementManager),
|
||||||
wrappedElement(elementManager->getElementById(json.value("element").toInt())),
|
wrappedElement(elementManager->getElementById(json.value("element").toInt())),
|
||||||
styles(LayerStyleContainer::fromJson(wrappedElement->isClosed(), json.value("styles").toArray()))
|
styles(LayerStyleContainer::fromJson(
|
||||||
|
wrappedElement->isClosed() ? LayerStyleContainer::TYPE_CLOSED : LayerStyleContainer::TYPE_UNCLOSED,
|
||||||
|
json.value("styles").toArray()))
|
||||||
{
|
{
|
||||||
qDebug() << json.value("name").toString() << " " << this;
|
qDebug() << json.value("name").toString() << " " << this;
|
||||||
if(wrappedElement != nullptr)
|
if(wrappedElement != nullptr)
|
||||||
|
|
|
@ -21,37 +21,37 @@ InfoDisplayWidget::InfoDisplayWidget(QWidget* parent) :QWidget(parent)
|
||||||
ui.rotation->setLabel(("旋转角度"));
|
ui.rotation->setLabel(("旋转角度"));
|
||||||
ui.scaleX->setLabel(("水平缩放"));
|
ui.scaleX->setLabel(("水平缩放"));
|
||||||
ui.scaleY->setLabel(("垂直缩放"));
|
ui.scaleY->setLabel(("垂直缩放"));
|
||||||
ui.rotation->setValidator(new QDoubleValidator(-10000, 10000, 6, this));
|
ui.rotation->setValidator(new QIntValidator(-360, 360, this));
|
||||||
ui.styleList->setDisabled(true);
|
ui.styleList->setDisabled(true);
|
||||||
connect(ui.rotation, &QLineEdit::textChanged, [=](QString content) {
|
connect(ui.rotation, &QLineEdit::textChanged, [=](const QString& content) {
|
||||||
if (fabs(content.toDouble() - this->displayLayer->property.rotation) < 1e-6)
|
if (fabs(content.toDouble() - this->displayLayer->property.rotation) < 1e-6)
|
||||||
return;
|
return;
|
||||||
this->displayLayer->property.rotation = content.toDouble();
|
this->displayLayer->property.setRotation(content.toDouble());
|
||||||
emit triggerCentralRefresh();
|
emit triggerCentralRefresh();
|
||||||
});
|
});
|
||||||
ui.offsetX->setValidator(new QDoubleValidator(-10000, 10000, 2, this));
|
ui.offsetX->setValidator(new QDoubleValidator(-10000, 10000, 2, this));
|
||||||
connect(ui.offsetX, &QLineEdit::textChanged, [=](QString content) {
|
connect(ui.offsetX, &QLineEdit::textChanged, [=](const QString& content) {
|
||||||
if (fabs(content.toDouble() - this->displayLayer->property.offset.x()) < 1e-6)
|
if (fabs(content.toDouble() - this->displayLayer->property.offset.x()) < 1e-6)
|
||||||
return;
|
return;
|
||||||
this->displayLayer->property.offset = { content.toDouble(), this->displayLayer->property.offset.y() };
|
this->displayLayer->property.offset = { content.toDouble(), this->displayLayer->property.offset.y() };
|
||||||
emit triggerCentralRefresh();
|
emit triggerCentralRefresh();
|
||||||
});
|
});
|
||||||
ui.offsetY->setValidator(new QDoubleValidator(-10000, 10000, 2, this));
|
ui.offsetY->setValidator(new QDoubleValidator(-10000, 10000, 2, this));
|
||||||
connect(ui.offsetY, &QLineEdit::textChanged, [=](QString content) {
|
connect(ui.offsetY, &QLineEdit::textChanged, [=](const QString& content) {
|
||||||
if (fabs(content.toDouble() - this->displayLayer->property.offset.y()) < 1e-6)
|
if (fabs(content.toDouble() - this->displayLayer->property.offset.y()) < 1e-6)
|
||||||
return;
|
return;
|
||||||
this->displayLayer->property.offset = { this->displayLayer->property.offset.x(), content.toDouble() };
|
this->displayLayer->property.offset = { this->displayLayer->property.offset.x(), content.toDouble() };
|
||||||
emit triggerCentralRefresh();
|
emit triggerCentralRefresh();
|
||||||
});
|
});
|
||||||
ui.scaleX->setValidator(new QDoubleValidator(0, 10000, 6, this));
|
ui.scaleX->setValidator(new QDoubleValidator(0, 10000, 6, this));
|
||||||
connect(ui.scaleX, &QLineEdit::textChanged, [=](QString content) {
|
connect(ui.scaleX, &QLineEdit::textChanged, [=](const QString& content) {
|
||||||
if (fabs(content.toDouble() - this->displayLayer->property.scale.x()) < 1e-6)
|
if (fabs(content.toDouble() - this->displayLayer->property.scale.x()) < 1e-6)
|
||||||
return;
|
return;
|
||||||
this->displayLayer->property.scale = { content.toDouble(), this->displayLayer->property.scale.y() };
|
this->displayLayer->property.scale = { content.toDouble(), this->displayLayer->property.scale.y() };
|
||||||
emit triggerCentralRefresh();
|
emit triggerCentralRefresh();
|
||||||
});
|
});
|
||||||
ui.scaleY->setValidator(new QDoubleValidator(0, 10000, 6, this));
|
ui.scaleY->setValidator(new QDoubleValidator(0, 10000, 6, this));
|
||||||
connect(ui.scaleY, &QLineEdit::textChanged, [=](QString content) {
|
connect(ui.scaleY, &QLineEdit::textChanged, [=](const QString& content) {
|
||||||
if (fabs(content.toDouble() - this->displayLayer->property.scale.y()) < 1e-6)
|
if (fabs(content.toDouble() - this->displayLayer->property.scale.y()) < 1e-6)
|
||||||
return;
|
return;
|
||||||
this->displayLayer->property.scale = { this->displayLayer->property.scale.x(), content.toDouble() };
|
this->displayLayer->property.scale = { this->displayLayer->property.scale.x(), content.toDouble() };
|
||||||
|
|
|
@ -0,0 +1,49 @@
|
||||||
|
#include "CppUnitTest.h"
|
||||||
|
#include "Editor/LayerStyle.h"
|
||||||
|
#include <QGuiApplication>
|
||||||
|
#include <QtWidgets/QApplication>
|
||||||
|
|
||||||
|
using namespace Microsoft::VisualStudio::CppUnitTestFramework;
|
||||||
|
|
||||||
|
namespace UnitTest
|
||||||
|
{
|
||||||
|
TEST_CLASS(LayerStyleContainerTest)
|
||||||
|
{
|
||||||
|
private:
|
||||||
|
char* argv[1];
|
||||||
|
int argc;
|
||||||
|
LayerStyleContainer containerParent, containerChild;
|
||||||
|
public:
|
||||||
|
LayerStyleContainerTest() :
|
||||||
|
argv{ const_cast<char*>("") }, argc(1),
|
||||||
|
containerParent(LayerStyleContainer::TYPE_ALL),
|
||||||
|
containerChild(LayerStyleContainer::TYPE_UNCLOSED)
|
||||||
|
{
|
||||||
|
QApplication app(argc, argv);
|
||||||
|
Assert::IsTrue(containerParent.empty());
|
||||||
|
Assert::IsTrue(containerChild.empty());
|
||||||
|
|
||||||
|
auto fillStyle = containerParent.makeUnusedStyle(FillElementLayerStyle::displayName());
|
||||||
|
Assert::IsTrue(containerParent.useStyle(std::shared_ptr(std::move(fillStyle))));
|
||||||
|
Assert::IsFalse(containerParent.empty());
|
||||||
|
Assert::IsFalse(containerParent.full());
|
||||||
|
|
||||||
|
auto strokeStyle = containerParent.makeUnusedStyle(StrokeElementLayerStyle::displayName());
|
||||||
|
containerParent.useStyle(std::shared_ptr(std::move(strokeStyle)));
|
||||||
|
|
||||||
|
auto childStrokeStyle = containerChild.makeUnusedStyle(StrokeElementLayerStyle::displayName());
|
||||||
|
containerChild.useStyle(std::shared_ptr(std::move(childStrokeStyle)));
|
||||||
|
Assert::IsTrue(containerChild.full());
|
||||||
|
|
||||||
|
containerParent.computeNewHash();
|
||||||
|
containerChild.computeNewHash();
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST_METHOD(ContainerCoverTest)
|
||||||
|
{
|
||||||
|
const auto newContainer = containerParent << containerChild;
|
||||||
|
Assert::IsTrue(newContainer.full());
|
||||||
|
Assert::AreEqual(newContainer.getHash(), containerChild.getHash());
|
||||||
|
}
|
||||||
|
};
|
||||||
|
}
|
|
@ -111,6 +111,7 @@
|
||||||
<DynamicSource Condition="'$(Configuration)|$(Platform)'=='Release|x64'">input</DynamicSource>
|
<DynamicSource Condition="'$(Configuration)|$(Platform)'=='Release|x64'">input</DynamicSource>
|
||||||
<QtMocFileName Condition="'$(Configuration)|$(Platform)'=='Release|x64'">%(Filename).moc</QtMocFileName>
|
<QtMocFileName Condition="'$(Configuration)|$(Platform)'=='Release|x64'">%(Filename).moc</QtMocFileName>
|
||||||
</ClCompile>
|
</ClCompile>
|
||||||
|
<ClCompile Include="LayerStyleTest.cpp" />
|
||||||
<ClCompile Include="PaintingTest.cpp">
|
<ClCompile Include="PaintingTest.cpp">
|
||||||
<DynamicSource Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">input</DynamicSource>
|
<DynamicSource Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">input</DynamicSource>
|
||||||
<QtMocFileName Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">%(Filename).moc</QtMocFileName>
|
<QtMocFileName Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">%(Filename).moc</QtMocFileName>
|
||||||
|
|
|
@ -51,5 +51,8 @@
|
||||||
<ClCompile Include="StyleTest.cpp">
|
<ClCompile Include="StyleTest.cpp">
|
||||||
<Filter>Source Files</Filter>
|
<Filter>Source Files</Filter>
|
||||||
</ClCompile>
|
</ClCompile>
|
||||||
|
<ClCompile Include="LayerStyleTest.cpp">
|
||||||
|
<Filter>Source Files</Filter>
|
||||||
|
</ClCompile>
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
</Project>
|
</Project>
|
Loading…
Reference in New Issue