WindowAppIsometricLineManager.cpp 5.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204
  1. #include "WindowAppIsometricLineManager.h"
  2. #include "WindowAppUiScene.h"
  3. WindowAppIsometricLineManager::WindowAppIsometricLineManager() :
  4. m_pScene(nullptr)
  5. {
  6. }
  7. /// <summary>
  8. /// 根据主控件和其他控件的关系进行等宽线的判断(核心逻辑)
  9. /// </summary>
  10. /// <param name="srcWidget"></param>
  11. /// <param name="dstWidgets"></param>
  12. void WindowAppIsometricLineManager::check(QWidget* srcWidget, QList<QWidget*> dstWidgets, STRETCH_DIRECTION dir)
  13. {
  14. // 由于等宽线只会在移动到某一个固定位置的时候出现,所以每次检查前都直接清空之前的重新绘制即可
  15. this->clear();
  16. // 是否有高度相同的控件
  17. // MEMO:先判断是否有高度相同,最后再根据拖拽的位置在决定在源控件的哪个方向上绘制等宽线
  18. // 因为各个目标控件的等宽线位置是固定的,固定在右侧和下侧,但是源控件根据拖拽位置不同而不同
  19. bool bSameHeight = false; // 是否有高度相同的控件
  20. bool bSameWidth = false; // 是否有宽度相同的控件
  21. // 遍历所有目标控件(只需要比较右侧和下侧即可)
  22. for (QWidget* dstWidget : dstWidgets)
  23. {
  24. // 首先检查高度
  25. bool bRet = this->checkHeight(srcWidget, dstWidget, dir);
  26. // 如果高度相同,那么设置一个源控件需要绘制高度方向等宽线的标记
  27. // 因为无论有多少个高度相同,源控件只需要绘制一次等高线
  28. bSameHeight ? bSameHeight : bSameHeight = bRet;
  29. // 继续检查宽度
  30. bRet = this->checkWidth(srcWidget, dstWidget, dir);
  31. // 如果宽度相同,那么设置一个源控件需要绘制宽度方向等宽线的标记
  32. bSameWidth ? bSameWidth : bSameWidth = bRet;
  33. }
  34. // 遍历完毕之后,判断是否需要绘制源控件的等宽线
  35. this->checkSourceWidget(srcWidget, bSameHeight, bSameWidth, dir);
  36. }
  37. /// <summary>
  38. /// 比较高度
  39. /// </summary>
  40. /// <param name="srcWidget"></param>
  41. /// <param name="dstWidget"></param>
  42. /// <param name="dir"></param>
  43. /// <returns>返回高度是否相同</returns>
  44. bool WindowAppIsometricLineManager::checkHeight(QWidget* srcWidget, QWidget* dstWidget, STRETCH_DIRECTION dir)
  45. {
  46. // 源边(仅比较右侧即可)
  47. QLine srcRighLine = Utility::getSideLineByID(srcWidget, (short)SIDE_DIRECTION::SIDE_RIGHT);
  48. // 目标边(仅比较右侧即可)
  49. QLine dstRightLine = Utility::getSideLineByID(dstWidget, (short)SIDE_DIRECTION::SIDE_RIGHT);
  50. // 比较右侧长度是否相同
  51. // 如果右侧相同
  52. if (srcRighLine.dy() == dstRightLine.dy())
  53. {
  54. // 如果拉伸的不是左右两侧,那么就需要绘制等高线
  55. if (dir != STRETCH_DIRECTION::DIR_LEFT && dir != STRETCH_DIRECTION::DIR_RIGHT)
  56. {
  57. // 生成一个新的等高线(高度方向)
  58. UI_ISOLINE_INFO newLine;
  59. newLine.pWidget = dstWidget;
  60. newLine.sideDir = SIDE_DIRECTION::SIDE_RIGHT;
  61. this->newIsoLine(newLine);
  62. // vDebug() << "Add height isometric line in [" << dstWidget << "] Side:" << (short)newLine.sideDir;
  63. // 返回高度相同
  64. return true;
  65. }
  66. }
  67. // 高度不相同
  68. return false;
  69. }
  70. /// <summary>
  71. /// 比较宽度
  72. /// </summary>
  73. /// <param name="srcWidget"></param>
  74. /// <param name="dstWidget"></param>
  75. /// <param name="dir"></param>
  76. /// <returns>返回宽度是否相同</returns>
  77. bool WindowAppIsometricLineManager::checkWidth(QWidget* srcWidget, QWidget* dstWidget, STRETCH_DIRECTION dir)
  78. {
  79. // 源边(仅比较下侧即可)
  80. QLine srcBottomLine = Utility::getSideLineByID(srcWidget, (short)SIDE_DIRECTION::SIDE_BOTTOM);
  81. // 目标边(仅比较下侧即可)
  82. QLine dstBottomLine = Utility::getSideLineByID(dstWidget, (short)SIDE_DIRECTION::SIDE_BOTTOM);
  83. // 比较下侧长度是否相同
  84. // 如果下侧相同
  85. if (srcBottomLine.dx() == dstBottomLine.dx())
  86. {
  87. // 如果拉伸的不是上下两侧,那么就需要绘制等宽线
  88. if (dir != STRETCH_DIRECTION::DIR_TOP && dir != STRETCH_DIRECTION::DIR_BOTTOM)
  89. {
  90. // 生成一个新的等宽线(宽度方向)
  91. UI_ISOLINE_INFO newLine;
  92. newLine.pWidget = dstWidget;
  93. newLine.sideDir = SIDE_DIRECTION::SIDE_BOTTOM;
  94. this->newIsoLine(newLine);
  95. // vDebug() << "Add width isometric line in [" << dstWidget << "] Side:" << (short)newLine.sideDir;
  96. // 返回高度相同
  97. return true;
  98. }
  99. }
  100. // 宽度不同
  101. return false;
  102. }
  103. /// <summary>
  104. /// 检查是否需要绘制源控件的等宽线
  105. /// </summary>
  106. /// <param name="srcWidget"></param>
  107. /// <param name="bSameHeight"></param>
  108. /// <param name="bSameWidth"></param>
  109. /// <param name="dir"></param>
  110. /// <returns></returns>
  111. bool WindowAppIsometricLineManager::checkSourceWidget(
  112. QWidget* srcWidget,
  113. bool bSameHeight,
  114. bool bSameWidth,
  115. STRETCH_DIRECTION dir
  116. )
  117. {
  118. // 如果高度相同,生成一个新的源控件等高线
  119. if (bSameHeight)
  120. {
  121. UI_ISOLINE_INFO newLine;
  122. newLine.pWidget = srcWidget;
  123. newLine.sideDir = SIDE_DIRECTION::SIDE_RIGHT; // 此处虽然是右侧,但是源控件的等宽线不一定生成在右侧
  124. newLine.stretchDir = dir;
  125. this->newIsoLine(newLine);
  126. }
  127. // 如果宽度相同,生成一个新的源控件等宽线
  128. if (bSameWidth)
  129. {
  130. UI_ISOLINE_INFO newLine;
  131. newLine.pWidget = srcWidget;
  132. newLine.sideDir = SIDE_DIRECTION::SIDE_BOTTOM; // 此处虽然是下侧,但是源控件的等宽线不一定生成在下侧
  133. newLine.stretchDir = dir;
  134. this->newIsoLine(newLine);
  135. }
  136. return false;
  137. }
  138. /// <summary>
  139. /// 清空所有的等宽线
  140. /// </summary>
  141. void WindowAppIsometricLineManager::clear()
  142. {
  143. QVector<WindowAppItemIsometricLine*>::iterator itr = m_IsoLines.begin();
  144. for (; itr != m_IsoLines.end();)
  145. {
  146. // 清空当前等宽线
  147. m_pScene->removeItem(*itr);
  148. itr = m_IsoLines.erase(itr);
  149. }
  150. this->m_IsoLines.clear();
  151. }
  152. /// <summary>
  153. /// 生成新的等宽线
  154. /// </summary>
  155. /// <param name="info"></param>
  156. void WindowAppIsometricLineManager::newIsoLine(const UI_ISOLINE_INFO& info)
  157. {
  158. // 根据对齐参数新建等宽线
  159. WindowAppItemIsometricLine* newLine = new WindowAppItemIsometricLine(info);
  160. // 添加到Scene
  161. m_pScene->addItem(newLine);
  162. // 加入到参考线组
  163. m_IsoLines.push_back(newLine);
  164. }