#include "WindowAppIsometricLineManager.h"
#include "WindowAppUiScene.h"
WindowAppIsometricLineManager::WindowAppIsometricLineManager() :
m_pScene(nullptr)
{
}
///
/// 根据主控件和其他控件的关系进行等宽线的判断(核心逻辑)
///
///
///
void WindowAppIsometricLineManager::check(QWidget* srcWidget, QList dstWidgets, STRETCH_DIRECTION dir)
{
// 由于等宽线只会在移动到某一个固定位置的时候出现,所以每次检查前都直接清空之前的重新绘制即可
this->clear();
// 是否有高度相同的控件
// MEMO:先判断是否有高度相同,最后再根据拖拽的位置在决定在源控件的哪个方向上绘制等宽线
// 因为各个目标控件的等宽线位置是固定的,固定在右侧和下侧,但是源控件根据拖拽位置不同而不同
bool bSameHeight = false; // 是否有高度相同的控件
bool bSameWidth = false; // 是否有宽度相同的控件
// 遍历所有目标控件(只需要比较右侧和下侧即可)
for (QWidget* dstWidget : dstWidgets)
{
// 首先检查高度
bool bRet = this->checkHeight(srcWidget, dstWidget, dir);
// 如果高度相同,那么设置一个源控件需要绘制高度方向等宽线的标记
// 因为无论有多少个高度相同,源控件只需要绘制一次等高线
bSameHeight ? bSameHeight : bSameHeight = bRet;
// 继续检查宽度
bRet = this->checkWidth(srcWidget, dstWidget, dir);
// 如果宽度相同,那么设置一个源控件需要绘制宽度方向等宽线的标记
bSameWidth ? bSameWidth : bSameWidth = bRet;
}
// 遍历完毕之后,判断是否需要绘制源控件的等宽线
this->checkSourceWidget(srcWidget, bSameHeight, bSameWidth, dir);
}
///
/// 比较高度
///
///
///
///
/// 返回高度是否相同
bool WindowAppIsometricLineManager::checkHeight(QWidget* srcWidget, QWidget* dstWidget, STRETCH_DIRECTION dir)
{
// 源边(仅比较右侧即可)
QLine srcRighLine = Utility::getSideLineByID(srcWidget, (short)SIDE_DIRECTION::SIDE_RIGHT);
// 目标边(仅比较右侧即可)
QLine dstRightLine = Utility::getSideLineByID(dstWidget, (short)SIDE_DIRECTION::SIDE_RIGHT);
// 比较右侧长度是否相同
// 如果右侧相同
if (srcRighLine.dy() == dstRightLine.dy())
{
// 如果拉伸的不是左右两侧,那么就需要绘制等高线
if (dir != STRETCH_DIRECTION::DIR_LEFT && dir != STRETCH_DIRECTION::DIR_RIGHT)
{
// 生成一个新的等高线(高度方向)
UI_ISOLINE_INFO newLine;
newLine.pWidget = dstWidget;
newLine.sideDir = SIDE_DIRECTION::SIDE_RIGHT;
this->newIsoLine(newLine);
// vDebug() << "Add height isometric line in [" << dstWidget << "] Side:" << (short)newLine.sideDir;
// 返回高度相同
return true;
}
}
// 高度不相同
return false;
}
///
/// 比较宽度
///
///
///
///
/// 返回宽度是否相同
bool WindowAppIsometricLineManager::checkWidth(QWidget* srcWidget, QWidget* dstWidget, STRETCH_DIRECTION dir)
{
// 源边(仅比较下侧即可)
QLine srcBottomLine = Utility::getSideLineByID(srcWidget, (short)SIDE_DIRECTION::SIDE_BOTTOM);
// 目标边(仅比较下侧即可)
QLine dstBottomLine = Utility::getSideLineByID(dstWidget, (short)SIDE_DIRECTION::SIDE_BOTTOM);
// 比较下侧长度是否相同
// 如果下侧相同
if (srcBottomLine.dx() == dstBottomLine.dx())
{
// 如果拉伸的不是上下两侧,那么就需要绘制等宽线
if (dir != STRETCH_DIRECTION::DIR_TOP && dir != STRETCH_DIRECTION::DIR_BOTTOM)
{
// 生成一个新的等宽线(宽度方向)
UI_ISOLINE_INFO newLine;
newLine.pWidget = dstWidget;
newLine.sideDir = SIDE_DIRECTION::SIDE_BOTTOM;
this->newIsoLine(newLine);
// vDebug() << "Add width isometric line in [" << dstWidget << "] Side:" << (short)newLine.sideDir;
// 返回高度相同
return true;
}
}
// 宽度不同
return false;
}
///
/// 检查是否需要绘制源控件的等宽线
///
///
///
///
///
///
bool WindowAppIsometricLineManager::checkSourceWidget(
QWidget* srcWidget,
bool bSameHeight,
bool bSameWidth,
STRETCH_DIRECTION dir
)
{
// 如果高度相同,生成一个新的源控件等高线
if (bSameHeight)
{
UI_ISOLINE_INFO newLine;
newLine.pWidget = srcWidget;
newLine.sideDir = SIDE_DIRECTION::SIDE_RIGHT; // 此处虽然是右侧,但是源控件的等宽线不一定生成在右侧
newLine.stretchDir = dir;
this->newIsoLine(newLine);
}
// 如果宽度相同,生成一个新的源控件等宽线
if (bSameWidth)
{
UI_ISOLINE_INFO newLine;
newLine.pWidget = srcWidget;
newLine.sideDir = SIDE_DIRECTION::SIDE_BOTTOM; // 此处虽然是下侧,但是源控件的等宽线不一定生成在下侧
newLine.stretchDir = dir;
this->newIsoLine(newLine);
}
return false;
}
///
/// 清空所有的等宽线
///
void WindowAppIsometricLineManager::clear()
{
QVector::iterator itr = m_IsoLines.begin();
for (; itr != m_IsoLines.end();)
{
// 清空当前等宽线
m_pScene->removeItem(*itr);
itr = m_IsoLines.erase(itr);
}
this->m_IsoLines.clear();
}
///
/// 生成新的等宽线
///
///
void WindowAppIsometricLineManager::newIsoLine(const UI_ISOLINE_INFO& info)
{
// 根据对齐参数新建等宽线
WindowAppItemIsometricLine* newLine = new WindowAppItemIsometricLine(info);
// 添加到Scene
m_pScene->addItem(newLine);
// 加入到参考线组
m_IsoLines.push_back(newLine);
}