#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); }