GridFrame/diagramCavas/source/diagramEditor/layoutCalculator.cpp

299 lines
9.8 KiB
C++
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

// LayoutCalculator.cpp
#include "diagramEditor/layoutCalculator.h"
#include "diagramEditor/diagramEditorWizard.h"
#include "graphicsDataModel/diagramEditorModel.h"
#include "diagramEditor/diagramEditorStructContainer.h"
#include "diagramEditor/diagramEditorBaseBlock.h"
#include "diagramEditor/editPanel.h"
#include "diagramEditor/editScene.h"
#include <QDebug>
FixedLayoutCalculator::FixedLayoutCalculator(DiagramEditorModel* model)
: m_model(model) {}
QMap<DiagramEditorBaseBlock*, QPointF> FixedLayoutCalculator::calculateLayout() {
m_blockPositions.clear();
if (!m_model) {
qWarning() << "FixedLayoutCalculator: Wizard为空";
return m_blockPositions;
}
auto mapTotal = m_model->getWizard()->getContainerStruct();
double deltaY = 0;
double lastMaxDownH = 0;
// 按层级顺序处理
for (auto iter = mapTotal.begin(); iter != mapTotal.end(); ++iter) {
int level = iter.key();
if (level == Constants::TRANSFORMER_LEVEL) {
continue; // 变压器特殊处理
}
// 创建层级布局
LevelLayout levelLayout;
levelLayout.level = level;
levelLayout.containers = iter.value();
if (levelLayout.containers.isEmpty()) {
continue;
}
// 第一阶段:计算尺寸
calculateContainerSizes(levelLayout);
// 第二阶段:计算位置
calculatePositions(levelLayout, deltaY, lastMaxDownH);
// 处理变压器在层级0之后
if (level == 0 && mapTotal.contains(Constants::TRANSFORMER_LEVEL)) {
auto transformers = mapTotal.value(Constants::TRANSFORMER_LEVEL);
if (!transformers.isEmpty()) {
calculateTransformerPositions(transformers, deltaY, lastMaxDownH);
}
}
}
return m_blockPositions;
}
void FixedLayoutCalculator::calculateContainerSizes(LevelLayout& levelLayout) {
levelLayout.maxUpHeight = 0;
levelLayout.maxDownHeight = 0;
for (auto& container : levelLayout.containers) {
if (!container) continue;
auto mapBlocks = container->getBlockMap();
// 计算上间隔尺寸
auto topBays = mapBlocks.value(0);
double maxUp = 0;
double widthUp = 0;
for (auto block : topBays) {
if (!block) continue;
QRectF rec = block->getRecSize();
maxUp = qMax(maxUp, rec.height());
widthUp += 100 + rec.width();
}
maxUp += Constants::EDITOR_ITEM_HEIGHT;
levelLayout.maxUpHeight = qMax(levelLayout.maxUpHeight, maxUp);
// 计算下间隔尺寸
auto bottomBays = mapBlocks.value(3);
double maxDown = 0;
double widthDown = 0;
for (auto block : bottomBays) {
if (!block) continue;
QRectF rec = block->getRecSize();
maxDown = qMax(maxDown, rec.height());
widthDown += 100 + rec.width();
}
maxDown += Constants::EDITOR_ITEM_HEIGHT;
levelLayout.maxDownHeight = qMax(levelLayout.maxDownHeight, maxDown);
// 计算母线宽度
double busWidth = 0;
auto bus1 = mapBlocks.value(1);
auto bus2 = mapBlocks.value(2);
if (!bus1.isEmpty()) {
busWidth = qMax(busWidth, bus1.first()->getRecSize().width());
}
if (!bus2.isEmpty()) {
busWidth = qMax(busWidth, bus2.first()->getRecSize().width());
}
// 计算容器宽度
double containerWidth = qMax(widthUp, widthDown);
if (containerWidth < busWidth) {
containerWidth = busWidth;
}
// 设置容器尺寸
container->setWidth(containerWidth);
}
// 处理空的情况
if (levelLayout.maxUpHeight == 0) {
levelLayout.maxUpHeight = Constants::EDITOR_ITEM_HEIGHT;
}
if (levelLayout.maxDownHeight == 0) {
levelLayout.maxDownHeight = Constants::EDITOR_ITEM_HEIGHT;
}
}
void FixedLayoutCalculator::calculatePositions(LevelLayout& levelLayout,
double& deltaY, double& lastMaxDownH) {
double startX = CONTAINER_START_X;
bool isFirstContainer = true;
for (auto& container : levelLayout.containers) {
if (!container) continue;
// 设置容器高度
container->setMaxUpH(levelLayout.maxUpHeight);
container->setMaxDownH(levelLayout.maxDownHeight);
// 计算垂直位置(每行第一个容器计算一次)
if (isFirstContainer) {
if (levelLayout.level == 0) { // 首行
deltaY = container->getMaxUpH();
} else { // 其他行
deltaY = deltaY + BUS_V_SPACING + lastMaxDownH + container->getMaxUpH();
}
lastMaxDownH = container->getMaxDownH();
isFirstContainer = false;
}
// 设置容器的关键Y坐标
container->setMidUpY(deltaY);
container->setMidDownY(deltaY + BUS_V_SPACING);
container->setStartX(startX);
// 计算容器内间隔位置
calculateBlockPositionsInContainer(container, startX, deltaY, deltaY + BUS_V_SPACING);
// 更新水平位置
startX += container->getWidth() + CONTAINER_H_SPACING;
}
}
void FixedLayoutCalculator::calculateBlockPositionsInContainer(DiagramEditorStructContainer* container,
double startX,
double midUpY,
double midDownY) {
if (!container) return;
auto mapBlocks = container->getBlockMap();
double currentX = startX;
for (auto it = mapBlocks.begin(); it != mapBlocks.end(); ++it) {
int layer = it.key();
auto blocks = it.value();
for (auto block : blocks) {
if (!block) continue;
QRectF rec = block->getRecSize();
QPointF centerOffset = block->getCenterOffset(); //参考中心与boundingrect中心的偏移量
QPointF center;
int blockType = block->getType();
if (blockType == 1) { // 母线
if (layer == 1) { // 母线1
center = QPointF(startX-20, midUpY + rec.height() * 0.5);
} else if (layer == 2) { // 母线2
center = QPointF(startX-20, midDownY - rec.height() * 0.5);
}
} else if (blockType == 2) { // 间隔
/*int nLayout = 0; //默认垂直
auto pBay = dynamic_cast<DiagramEditorBayBlock*>(block);
if(pBay){
nLayout = pBay->getBayInfo().nLayout;
}*/
if (layer == 0) { // 上间隔
center = QPointF(currentX + rec.width() * 0.5,
midUpY - rec.height() * 0.5 + centerOffset.y() - Constants::EDITOR_ITEM_HEIGHT * 0.5);
} else if (layer == 3) { // 下间隔
center = QPointF(currentX + rec.width() * 0.5,
midDownY + rec.height() * 0.5 + centerOffset.y() + Constants::EDITOR_ITEM_HEIGHT * 0.5);
}
currentX += rec.width();
}
// 变压器不在这里处理
if (!center.isNull()) {
m_blockPositions[block] = center;
block->setSeceneDelta(center);
}
}
}
}
void FixedLayoutCalculator::calculateTransformerPositions(
const QList<DiagramEditorStructContainer*>& transformers,
double& deltaY, double& lastMaxDownH)
{
if (transformers.isEmpty())
return;
// ---------- ① 计算变压器尺寸 ----------
for (auto container : transformers) {
if (!container)
continue;
auto mapBlocks = container->getBlockMap();
auto transBlocks = mapBlocks.value(1); // layer 1
if (transBlocks.isEmpty())
continue;
for (auto block : transBlocks) {
if (!block)
continue;
QRectF rec = block->getRecSize();
container->setWidth(rec.width());
container->setHeight(rec.height());
break; // 仍然只取第一个
}
}
// ---------- ② 纵向位置(保持不变) ----------
double centerY = 0;
if (!transformers.isEmpty()) {
deltaY += CONTAINER_H_SPACING + lastMaxDownH + transformers.first()->getHeight();
centerY = deltaY - transformers.first()->getHeight() * 0.5;
}
// ---------- ③ 固定宽度水平布局 ----------
double sceneWidth = m_model->getPanel()->getScene()->width();
const int count = transformers.size();
// 没有变压器,直接返回
if (count == 0)
return;
// 等间距分布(含左右边距)
const double spacing = sceneWidth / (count + 1);
// ---------- ④ 逐个放置 ----------
for (int i = 0; i < count; ++i) {
auto container = transformers.at(i);
if (!container)
continue;
container->setStartY(centerY);
// 计算水平中心
const double centerX = spacing * (i + 1);
const double startX = centerX - container->getWidth() * 0.5;
container->setStartX(startX);
// ---------- ⑤ 内部 block 居中 ----------
auto mapBlocks = container->getBlockMap();
for (auto it = mapBlocks.begin(); it != mapBlocks.end(); ++it) {
for (auto block : it.value()) {
if (!block)
continue;
QRectF rec = block->getRecSize();
QPointF pos(
startX + rec.width() * 0.5,
centerY + rec.height() * 0.5
);
m_blockPositions[block] = pos;
block->setSeceneDelta(pos);
}
}
}
}