[editor/style] 修改了style相关的GUI

* 为LayerStyleDialog提供最大大小和滚动条 | #30
* 为StrokeElementLayerStyle适配变宽样式 | #33
main
ArgonarioD 2023-03-28 19:51:35 +08:00
parent 1295e2255a
commit bb7c30a896
6 changed files with 187 additions and 36 deletions

View File

@ -1,7 +1,10 @@
#include "LayerStyleDialog.h" #include "LayerStyleDialog.h"
#include <QGuiApplication>
#include <QComboBox> #include <QComboBox>
#include <QDialogButtonBox> #include <QDialogButtonBox>
#include <QGridLayout> #include <QGridLayout>
#include <QScreen>
#include <QScrollBar>
LayerStyleDialog::LayerStyleDialog( LayerStyleDialog::LayerStyleDialog(
LayerStyleContainer* pStyles, LayerStyleContainer* pStyles,
@ -13,13 +16,16 @@ LayerStyleDialog::LayerStyleDialog(
dialogLayout->setAlignment(Qt::AlignmentFlag::AlignHCenter); dialogLayout->setAlignment(Qt::AlignmentFlag::AlignHCenter);
this->setLayout(dialogLayout); this->setLayout(dialogLayout);
styleScrollArea = new QScrollArea(this);
dialogLayout->addWidget(styleScrollArea, 1, 0);
if (existedStyle) if (existedStyle)
{ {
this->modifyingStyle = existedStyle->clone(); this->modifyingStyle = existedStyle->clone();
this->styleWidget = modifyingStyle->getInputWidget(); this->styleWidget = modifyingStyle->getInputWidget();
this->styleWidget->setParent(this); this->styleWidget->setParent(this);
dialogLayout->addWidget(styleWidget, 1, 0); styleScrollArea->setWidget(styleWidget);
} }
else else
{ {
@ -36,7 +42,7 @@ LayerStyleDialog::LayerStyleDialog(
this->styleWidget = this->modifyingStyle->getInputWidget(); this->styleWidget = this->modifyingStyle->getInputWidget();
this->styleWidget->setParent(this); this->styleWidget->setParent(this);
this->dialogLayout->addWidget(styleWidget, 1, 0); styleScrollArea->setWidget(styleWidget);
connect(typeSelector, &QComboBox::currentTextChanged, connect(typeSelector, &QComboBox::currentTextChanged,
this, &LayerStyleDialog::onStyleTypeSelectorChanged); this, &LayerStyleDialog::onStyleTypeSelectorChanged);
} }
@ -45,6 +51,11 @@ LayerStyleDialog::LayerStyleDialog(
connect(buttonBox, &QDialogButtonBox::accepted, this, &LayerStyleDialog::accept); connect(buttonBox, &QDialogButtonBox::accepted, this, &LayerStyleDialog::accept);
connect(buttonBox, &QDialogButtonBox::rejected, this, &LayerStyleDialog::reject); connect(buttonBox, &QDialogButtonBox::rejected, this, &LayerStyleDialog::reject);
dialogLayout->addWidget(buttonBox, 2, 0); dialogLayout->addWidget(buttonBox, 2, 0);
const auto* screen = QGuiApplication::screenAt(this->geometry().center());
this->setMaximumHeight(screen->geometry().height() / 4 * 3);
styleScrollArea->setMinimumWidth(styleWidget->width() + styleScrollArea->verticalScrollBar()->width() + 2);
styleScrollArea->adjustSize();
styleScrollArea->setWidgetResizable(true);
this->adjustSize(); this->adjustSize();
} }
@ -56,16 +67,13 @@ void LayerStyleDialog::accept()
void LayerStyleDialog::onStyleTypeSelectorChanged(const QString& current) void LayerStyleDialog::onStyleTypeSelectorChanged(const QString& current)
{ {
if (this->styleWidget)
{
this->dialogLayout->removeWidget(this->styleWidget);
this->styleWidget->setParent(nullptr);
delete styleWidget;
}
this->modifyingStyle = std::move(styles->makeUnusedStyle(current)); this->modifyingStyle = std::move(styles->makeUnusedStyle(current));
this->styleWidget->deleteLater();
this->styleWidget = this->modifyingStyle->getInputWidget(); this->styleWidget = this->modifyingStyle->getInputWidget();
this->styleWidget->setParent(this); this->styleWidget->setParent(this);
this->dialogLayout->addWidget(styleWidget, 1, 0); //this->dialogLayout->addWidget(styleWidget, 1, 0);
this->styleScrollArea->setWidget(styleWidget);
styleScrollArea->setMinimumWidth(styleWidget->width() + styleScrollArea->verticalScrollBar()->width() + 2);
this->styleWidget->adjustSize(); this->styleWidget->adjustSize();
this->adjustSize(); this->adjustSize();
} }

View File

@ -1,6 +1,7 @@
#pragma once #pragma once
#include "LayerStyle.h" #include "LayerStyle.h"
#include <QDialog> #include <QDialog>
#include <QScrollArea>
#include <QGridLayout> #include <QGridLayout>
class LayerStyleDialog : public QDialog class LayerStyleDialog : public QDialog
@ -9,6 +10,7 @@ class LayerStyleDialog : public QDialog
private: private:
QWidget* styleWidget; QWidget* styleWidget;
QGridLayout* dialogLayout; QGridLayout* dialogLayout;
QScrollArea* styleScrollArea;
LayerStyleContainer* styles; LayerStyleContainer* styles;
std::unique_ptr<LayerStyle> modifyingStyle; std::unique_ptr<LayerStyle> modifyingStyle;
public: public:

View File

@ -8,12 +8,18 @@
#include <ranges> #include <ranges>
#include <utility> #include <utility>
// Stroke Table
constexpr int COLUMN_WIDTH = 0; constexpr int COLUMN_WIDTH = 0;
constexpr int COLUMN_COLOR = 1; constexpr int COLUMN_COLOR = 1;
constexpr int COLUMN_METALLIC = 2; constexpr int COLUMN_METALLIC = 2;
constexpr int COLUMN_ROUGHNESS = 3; constexpr int COLUMN_ROUGHNESS = 3;
constexpr int COLUMN_OPERATIONS = 4; constexpr int COLUMN_OPERATIONS = 4;
// Width Table
constexpr int COLUMN_LENGTH = 0;
constexpr int COLUMN_WIDTH_RATIO = 1;
constexpr int COLUMN_WIDTH_OPERATIONS = 2;
inline Renderer::Material newMaterial() inline Renderer::Material newMaterial()
{ {
return {ColorHelper::instance().getPrimary1()}; return {ColorHelper::instance().getPrimary1()};
@ -47,11 +53,15 @@ StrokeStyleWidget::StrokeStyleWidget(
viewLayout->addWidget(strokeProperties); viewLayout->addWidget(strokeProperties);
viewLayout->addWidget(widthField); viewLayout->addWidget(widthField);
initTable(radialStroke(stroke)); initStrokeTable(radialStroke(stroke));
viewLayout->addWidget(strokeTable); viewLayout->addWidget(strokeTable);
initAddButton(); initStrokeAddButton();
viewLayout->addWidget(addButton); viewLayout->addWidget(addButton);
initWidthWidget();
viewLayout->addWidget(enableVariableWidth);
viewLayout->addWidget(widthWidget);
this->adjustSize(); this->adjustSize();
} }
@ -97,12 +107,10 @@ void StrokeStyleWidget::initStrokeSettings()
}); });
} }
void StrokeStyleWidget::initTable(const std::shared_ptr<Renderer::StrokeRadialGradient>& materialStroke) void StrokeStyleWidget::initStrokeTable(const std::shared_ptr<Renderer::StrokeRadialGradient>& materialStroke)
{ {
this->strokeTable = new QTableWidget(this); this->strokeTable = new QTableWidget(materialStroke->materialMap.size(), 5, this);
strokeTable->setSizeAdjustPolicy(QAbstractScrollArea::AdjustToContentsOnFirstShow); strokeTable->setSizeAdjustPolicy(QAbstractScrollArea::AdjustToContentsOnFirstShow);
strokeTable->setColumnCount(5);
strokeTable->setRowCount(materialStroke->materialMap.size());
QStringList headers; QStringList headers;
headers << QStringLiteral("ÀëÐľàÀëÕ¼±È") headers << QStringLiteral("ÀëÐľàÀëÕ¼±È")
<< QStringLiteral("ÑÕÉ«") << QStringLiteral("ÑÕÉ«")
@ -116,14 +124,15 @@ void StrokeStyleWidget::initTable(const std::shared_ptr<Renderer::StrokeRadialGr
// ÄÚÈÝ // ÄÚÈÝ
for (auto& [width, material] : std::views::reverse(materialStroke->materialMap)) for (auto& [width, material] : std::views::reverse(materialStroke->materialMap))
{ {
setTableRow(row, width, material); setStrokeTableRow(row, width, material);
row++; row++;
} }
connect(strokeTable, &QTableWidget::currentItemChanged, this, &StrokeStyleWidget::onCurrentItemChanged); // 记录currentItemChanged是为了能够在变更宽度map的key时也能取到原本的值
connect(strokeTable, &QTableWidget::cellChanged, this, &StrokeStyleWidget::onCellChanged); connect(strokeTable, &QTableWidget::currentItemChanged, this, &StrokeStyleWidget::onStrokeCurrentItemChanged);
connect(strokeTable, &QTableWidget::cellChanged, this, &StrokeStyleWidget::onStrokeCellChanged);
} }
void StrokeStyleWidget::initAddButton() void StrokeStyleWidget::initStrokeAddButton()
{ {
this->addButton = new QtMaterialRaisedButton("+", strokeTable); this->addButton = new QtMaterialRaisedButton("+", strokeTable);
addButton->setFixedHeight(30); addButton->setFixedHeight(30);
@ -145,13 +154,91 @@ void StrokeStyleWidget::initAddButton()
materialMap[newWidth] = newMaterial; materialMap[newWidth] = newMaterial;
const int newRow = this->strokeTable->rowCount(); const int newRow = this->strokeTable->rowCount();
this->strokeTable->insertRow(newRow); this->strokeTable->insertRow(newRow);
setTableRow(newRow, newWidth, materialMap[newWidth]); setStrokeTableRow(newRow, newWidth, materialMap[newWidth]);
this->strokeTable->update(); this->strokeTable->update();
handlingRowInsert = false; handlingRowInsert = false;
}); });
} }
void StrokeStyleWidget::setTableRow(int row, float width, Renderer::Material& material) void StrokeStyleWidget::initWidthWidget()
{
this->enableVariableWidth = new QtMaterialCheckBox(this);
this->widthWidget = new QWidget(this);
auto* widthWidgetLayout = new QVBoxLayout(widthWidget);
this->widthTable = new QTableWidget(stroke->widthMap.size(), 3, widthWidget);
this->widthAddButton = new QtMaterialRaisedButton("+", widthWidget);
widthWidgetLayout->addWidget(widthTable);
widthWidgetLayout->addWidget(widthAddButton);
enableVariableWidth->setText(QStringLiteral("宽度可变"));
connect(enableVariableWidth, &QtMaterialCheckBox::toggled, [this](bool checked){
widthWidget->setVisible(checked);
if (!checked)
{
stroke->widthMap.clear();
}
});
widthWidget->setVisible(!stroke->widthMap.empty());
enableVariableWidth->setChecked(!stroke->widthMap.empty());
QStringList headerLabels;
headerLabels << QStringLiteral("长度占比") << QStringLiteral("宽度缩放比") << QStringLiteral("其他操作");
widthTable->setHorizontalHeaderLabels(headerLabels);
widthTable->setMinimumHeight(widthTable->horizontalHeader()->height() * 4);
widthTable->setMinimumWidth(widthTable->sizeHint().width());
widthTable->setSizeAdjustPolicy(QAbstractScrollArea::AdjustToContentsOnFirstShow);
for (int row = 0; const auto& [length, widthRatio] : stroke->widthMap)
{
setWidthTableRow(row, length, widthRatio);
++row;
}
connect(widthTable, &QTableWidget::currentItemChanged, this, &StrokeStyleWidget::onWidthCurrentItemChanged);
connect(widthTable, &QTableWidget::cellChanged, this, &StrokeStyleWidget::onWidthCellChanged);
widthAddButton->setFixedHeight(30);
widthAddButton->setBackgroundColor(ColorHelper::instance().getPrimary1());
connect(widthAddButton, &QtMaterialRaisedButton::clicked, [this] {
auto& widthMap = stroke->widthMap;
float newLength;
if (widthMap.empty())
{
newLength = 1.f;
}
else
{
const auto firstPair = widthMap.begin();
newLength = firstPair->first / 2;
}
widthMap[newLength] = 1.f;
const int newRow = this->widthTable->rowCount();
this->widthTable->insertRow(newRow);
setWidthTableRow(newRow, newLength, widthMap[newLength]);
this->widthTable->update();
});
}
void StrokeStyleWidget::setWidthTableRow(int row, float length, float ratio)
{
auto* lengthItem = new QTableWidgetItem;
lengthItem->setData(Qt::EditRole, length);
widthTable->setItem(row, COLUMN_LENGTH, lengthItem);
auto* widthRatioItem = new QTableWidgetItem;
widthRatioItem->setData(Qt::EditRole, ratio);
widthTable->setItem(row, COLUMN_WIDTH_RATIO, widthRatioItem);
auto* removeButton = new QtMaterialRaisedButton("-", widthTable);
removeButton->setBackgroundColor(ColorHelper::instance().getPrimary1());
removeButton->setFixedSize(20, 20);
widthTable->setCellWidget(row, COLUMN_WIDTH_OPERATIONS, removeButton);
connect(removeButton, &QtMaterialRaisedButton::clicked, [this, lengthItem] {
stroke->widthMap.erase(lengthItem->data(Qt::EditRole).toFloat());
this->widthTable->removeRow(lengthItem->row());
});
}
void StrokeStyleWidget::setStrokeTableRow(int row, float width, Renderer::Material& material)
{ {
auto* widthItem = new QTableWidgetItem; auto* widthItem = new QTableWidgetItem;
widthItem->setData(Qt::EditRole, width); widthItem->setData(Qt::EditRole, width);
@ -186,24 +273,24 @@ void StrokeStyleWidget::setTableRow(int row, float width, Renderer::Material& ma
}); });
} }
void StrokeStyleWidget::onCurrentItemChanged(QTableWidgetItem* current, QTableWidgetItem* previous) void StrokeStyleWidget::onStrokeCurrentItemChanged(QTableWidgetItem* current, QTableWidgetItem* previous)
{ {
if (!current) return; if (!current) return;
const int column = current->column(); const int column = current->column();
if (column != COLUMN_COLOR && column != COLUMN_OPERATIONS) if (column != COLUMN_COLOR && column != COLUMN_OPERATIONS)
{ {
this->currentItemValue = current->data(Qt::EditRole); this->currentStrokeItemValue = current->data(Qt::EditRole);
} }
} }
void StrokeStyleWidget::onCellChanged(int row, int column) void StrokeStyleWidget::onStrokeCellChanged(int row, int column)
{ {
if (handlingRowInsert) return; if (handlingRowInsert) return;
const auto changedItem = strokeTable->item(row, column); const auto changedItem = strokeTable->item(row, column);
const auto changedItemValue = changedItem->text().toFloat(); const auto changedItemValue = changedItem->data(Qt::EditRole).toFloat();
if (changedItemValue < 0 || 1 < changedItemValue) if (changedItemValue < 0 || 1 < changedItemValue)
{ {
changedItem->setData(Qt::EditRole, this->currentItemValue.toFloat()); changedItem->setData(Qt::EditRole, this->currentStrokeItemValue.toFloat());
return; return;
} }
const auto changedWidth = strokeTable->item(row, COLUMN_WIDTH)->data(Qt::EditRole).toFloat(); const auto changedWidth = strokeTable->item(row, COLUMN_WIDTH)->data(Qt::EditRole).toFloat();
@ -211,7 +298,7 @@ void StrokeStyleWidget::onCellChanged(int row, int column)
{ {
case COLUMN_WIDTH: case COLUMN_WIDTH:
{ {
float oldWidth = this->currentItemValue.toFloat(); float oldWidth = this->currentStrokeItemValue.toFloat();
auto node = radialStroke(stroke)->materialMap.extract(oldWidth); auto node = radialStroke(stroke)->materialMap.extract(oldWidth);
if (node.empty()) if (node.empty())
{ {
@ -233,4 +320,47 @@ void StrokeStyleWidget::onCellChanged(int row, int column)
break; break;
} }
} }
}
void StrokeStyleWidget::onWidthCurrentItemChanged(QTableWidgetItem* current, QTableWidgetItem* previous)
{
if (!current) return;
const int column = current->column();
if (column != COLUMN_WIDTH_OPERATIONS)
{
this->currentWidthItemValue = current->data(Qt::EditRole);
}
}
void StrokeStyleWidget::onWidthCellChanged(int row, int column)
{
const auto changedItem = widthTable->item(row, column);
const auto changedItemValue = changedItem->data(Qt::EditRole).toFloat();
if (column == COLUMN_LENGTH && (changedItemValue < 0 || 1 < changedItemValue))
{
changedItem->setData(Qt::EditRole, this->currentWidthItemValue.toFloat());
return;
}
const auto changedLength = widthTable->item(row, COLUMN_LENGTH)->data(Qt::EditRole).toFloat();
switch (column)
{
case COLUMN_LENGTH:
{
float oldLength = this->currentWidthItemValue.toFloat();
auto node = stroke->widthMap.extract(oldLength);
if (node.empty())
{
break;
}
node.key() = changedLength;
stroke->widthMap.insert(std::move(node));
strokeTable->sortItems(COLUMN_LENGTH, Qt::DescendingOrder);
break;
}
case COLUMN_WIDTH_RATIO:
{
stroke->widthMap[changedLength] = changedItemValue;
break;
}
}
} }

View File

@ -11,26 +11,37 @@ class StrokeStyleWidget : public QWidget
{ {
Q_OBJECT Q_OBJECT
private: private:
QVariant currentItemValue; QVariant currentStrokeItemValue;
QVariant currentWidthItemValue;
QtMaterialCheckBox* enableGradual; QtMaterialCheckBox* enableGradual;
QComboBox* endTypeBox; QComboBox* endTypeBox;
QtMaterialTextField* widthField; QtMaterialTextField* widthField;
QTableWidget* strokeTable; QTableWidget* strokeTable;
QtMaterialRaisedButton* addButton; QtMaterialRaisedButton* addButton;
QtMaterialCheckBox* enableVariableWidth;
QWidget* widthWidget;
QTableWidget* widthTable;
QtMaterialRaisedButton* widthAddButton;
bool handlingRowInsert = false; bool handlingRowInsert = false;
void initStrokeSettings(); void initStrokeSettings();
void initTable(const std::shared_ptr<Renderer::StrokeRadialGradient>& materialStroke); void initStrokeTable(const std::shared_ptr<Renderer::StrokeRadialGradient>& materialStroke);
void initAddButton(); void setStrokeTableRow(int row, float width, Renderer::Material& material);
void setTableRow(int row, float width, Renderer::Material& material); void initStrokeAddButton();
void initWidthWidget();
void setWidthTableRow(int row, float length, float ratio);
public: public:
StrokeStyleWidget(const std::shared_ptr<MaterialStyleStroke>& stroke, QWidget* parent = nullptr); StrokeStyleWidget(const std::shared_ptr<MaterialStyleStroke>& stroke, QWidget* parent = nullptr);
std::shared_ptr<MaterialStyleStroke> stroke; std::shared_ptr<MaterialStyleStroke> stroke;
protected slots: protected slots:
void onCurrentItemChanged(QTableWidgetItem* current, QTableWidgetItem* previous); void onStrokeCurrentItemChanged(QTableWidgetItem* current, QTableWidgetItem* previous);
void onCellChanged(int row, int column); void onStrokeCellChanged(int row, int column);
void onWidthCurrentItemChanged(QTableWidgetItem* current, QTableWidgetItem* previous);
void onWidthCellChanged(int row, int column);
}; };

View File

@ -41,7 +41,6 @@ std::vector<Renderer::BaseStyle> StrokeElementLayerStyle::toBaseStyles() const
QWidget* StrokeElementLayerStyle::getInputWidget() QWidget* StrokeElementLayerStyle::getInputWidget()
{ {
auto* w = new QWidget; auto* w = new QWidget;
auto* materialList = new QListView;
auto* layout = new QVBoxLayout(w); auto* layout = new QVBoxLayout(w);
layout->setMargin(0); layout->setMargin(0);

View File

@ -103,7 +103,7 @@ std::vector<GLfloat> Renderer::MaterialStyleStroke::encoded() const
std::unique_ptr<MaterialStyle> Renderer::MaterialStyleStroke::clone() const std::unique_ptr<MaterialStyle> Renderer::MaterialStyleStroke::clone() const
{ {
return std::make_unique<MaterialStyleStroke>(halfWidth, strokeType, endType, materialStroke->clone()); return std::make_unique<MaterialStyleStroke>(halfWidth, strokeType, endType, materialStroke->clone(), widthMap);
} }
bool Renderer::MaterialStyleStroke::operator==(const MaterialStyle& m) const bool Renderer::MaterialStyleStroke::operator==(const MaterialStyle& m) const
@ -112,7 +112,8 @@ bool Renderer::MaterialStyleStroke::operator==(const MaterialStyle& m) const
&& halfWidth == static_cast<const MaterialStyleStroke&>(m).halfWidth && halfWidth == static_cast<const MaterialStyleStroke&>(m).halfWidth
&& strokeType == static_cast<const MaterialStyleStroke&>(m).strokeType && strokeType == static_cast<const MaterialStyleStroke&>(m).strokeType
&& endType == static_cast<const MaterialStyleStroke&>(m).endType && endType == static_cast<const MaterialStyleStroke&>(m).endType
&& *materialStroke == *static_cast<const MaterialStyleStroke&>(m).materialStroke; && *materialStroke == *static_cast<const MaterialStyleStroke&>(m).materialStroke
&& widthMap == static_cast<const MaterialStyleStroke&>(m).widthMap;
} }
float Renderer::MaterialStyleStroke::getHalfWidth() const float Renderer::MaterialStyleStroke::getHalfWidth() const