[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)
|
||||
{
|
||||
container.useStyle(LayerStyle::fromJson(style.toObject()));
|
||||
|
@ -102,20 +102,20 @@ LayerStyleContainer LayerStyleContainer::fromJson(bool isClosedElement, const QJ
|
|||
return container;
|
||||
}
|
||||
|
||||
LayerStyleContainer::LayerStyleContainer(bool isClosedElement) : hash(0)
|
||||
LayerStyleContainer::LayerStyleContainer(ElementType elementType) : hash(0)
|
||||
{
|
||||
for (const auto& style : commonStyles)
|
||||
{
|
||||
unusedStyles.insert(style);
|
||||
}
|
||||
if (isClosedElement)
|
||||
if (elementType & LayerStyleContainer::TYPE_CLOSED)
|
||||
{
|
||||
for (const auto& style : closedOnlyStyles)
|
||||
{
|
||||
unusedStyles.insert(style);
|
||||
}
|
||||
}
|
||||
else
|
||||
if (elementType & LayerStyleContainer::TYPE_UNCLOSED)
|
||||
{
|
||||
for (const auto& style : unclosedOnlyStyles)
|
||||
{
|
||||
|
@ -182,13 +182,29 @@ std::map<QString, std::shared_ptr<LayerStyle>>::iterator LayerStyleContainer::en
|
|||
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 (!forceOverride || !styles.contains(styleDisplayName))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
styles[styleDisplayName] = style;
|
||||
return true;
|
||||
}
|
||||
styles[styleNode.key()] = style;
|
||||
usedStyles.insert(std::move(styleNode));
|
||||
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);
|
||||
}
|
||||
|
||||
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)
|
||||
{
|
||||
auto ptr = std::make_unique<StrokeElementLayerStyle>(
|
||||
|
|
|
@ -116,27 +116,35 @@ private:
|
|||
std::map<QString, std::shared_ptr<LayerStyle>> styles;
|
||||
size_t hash;
|
||||
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);
|
||||
std::vector<Renderer::BaseStyle> toBaseStyles() const override;
|
||||
QJsonArray toJson() const;
|
||||
static LayerStyleContainer fromJson(ElementType elementType, const QJsonArray& jsonArray);
|
||||
|
||||
bool empty() const;
|
||||
bool full() const;
|
||||
std::map<QString, std::shared_ptr<LayerStyle>>::iterator begin();
|
||||
std::map<QString, std::shared_ptr<LayerStyle>>::iterator end();
|
||||
LayerStyleContainer(ElementType elementType);
|
||||
[[nodiscard]] std::vector<Renderer::BaseStyle> toBaseStyles() const override;
|
||||
[[nodiscard]] QJsonArray toJson() const;
|
||||
|
||||
QStringList unusedStyleNames() const;
|
||||
std::unique_ptr<LayerStyle> makeUnusedStyle(const QString& styleName) const;
|
||||
bool useStyle(const std::shared_ptr<LayerStyle>& style);
|
||||
[[nodiscard]] bool empty() const;
|
||||
[[nodiscard]] bool full() const;
|
||||
[[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 dropStyle(const QString& styleName);
|
||||
std::shared_ptr<LayerStyle> getStyle(const QString& styleName) const;
|
||||
float boundingBoxAffectValue() const;
|
||||
size_t getHash() const;
|
||||
[[nodiscard]] std::shared_ptr<LayerStyle> getStyle(const QString& styleName) const;
|
||||
[[nodiscard]] float boundingBoxAffectValue() 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)
|
||||
: LayerWrapper(json, parent, elementManager),
|
||||
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;
|
||||
if(wrappedElement != nullptr)
|
||||
|
|
|
@ -21,37 +21,37 @@ InfoDisplayWidget::InfoDisplayWidget(QWidget* parent) :QWidget(parent)
|
|||
ui.rotation->setLabel(("旋转角度"));
|
||||
ui.scaleX->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);
|
||||
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)
|
||||
return;
|
||||
this->displayLayer->property.rotation = content.toDouble();
|
||||
this->displayLayer->property.setRotation(content.toDouble());
|
||||
emit triggerCentralRefresh();
|
||||
});
|
||||
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)
|
||||
return;
|
||||
this->displayLayer->property.offset = { content.toDouble(), this->displayLayer->property.offset.y() };
|
||||
emit triggerCentralRefresh();
|
||||
});
|
||||
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)
|
||||
return;
|
||||
this->displayLayer->property.offset = { this->displayLayer->property.offset.x(), content.toDouble() };
|
||||
emit triggerCentralRefresh();
|
||||
});
|
||||
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)
|
||||
return;
|
||||
this->displayLayer->property.scale = { content.toDouble(), this->displayLayer->property.scale.y() };
|
||||
emit triggerCentralRefresh();
|
||||
});
|
||||
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)
|
||||
return;
|
||||
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>
|
||||
<QtMocFileName Condition="'$(Configuration)|$(Platform)'=='Release|x64'">%(Filename).moc</QtMocFileName>
|
||||
</ClCompile>
|
||||
<ClCompile Include="LayerStyleTest.cpp" />
|
||||
<ClCompile Include="PaintingTest.cpp">
|
||||
<DynamicSource Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">input</DynamicSource>
|
||||
<QtMocFileName Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">%(Filename).moc</QtMocFileName>
|
||||
|
|
|
@ -51,5 +51,8 @@
|
|||
<ClCompile Include="StyleTest.cpp">
|
||||
<Filter>Source Files</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="LayerStyleTest.cpp">
|
||||
<Filter>Source Files</Filter>
|
||||
</ClCompile>
|
||||
</ItemGroup>
|
||||
</Project>
|
Loading…
Reference in New Issue