DefaultHorizontalNodeGeometry.cpp 7.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239
  1. #include "DefaultHorizontalNodeGeometry.hpp"
  2. #include "AbstractGraphModel.hpp"
  3. #include "NodeData.hpp"
  4. #include <QPoint>
  5. #include <QRect>
  6. #include <QWidget>
  7. namespace QtNodes {
  8. DefaultHorizontalNodeGeometry::DefaultHorizontalNodeGeometry(AbstractGraphModel &graphModel)
  9. : AbstractNodeGeometry(graphModel)
  10. , _portSize(20)
  11. , _portSpasing(10)
  12. , _fontMetrics(QFont())
  13. , _boldFontMetrics(QFont())
  14. {
  15. QFont f;
  16. f.setBold(true);
  17. _boldFontMetrics = QFontMetrics(f);
  18. _portSize = _fontMetrics.height();
  19. }
  20. QSize DefaultHorizontalNodeGeometry::size(NodeId const nodeId) const
  21. {
  22. return _graphModel.nodeData<QSize>(nodeId, NodeRole::Size);
  23. }
  24. void DefaultHorizontalNodeGeometry::recomputeSize(NodeId const nodeId) const
  25. {
  26. unsigned int height = maxVerticalPortsExtent(nodeId);
  27. if (auto w = _graphModel.nodeData<QWidget *>(nodeId, NodeRole::Widget)) {
  28. height = std::max(height, static_cast<unsigned int>(w->height()));
  29. }
  30. QRectF const capRect = captionRect(nodeId);
  31. height += capRect.height();
  32. height += _portSpasing; // space above caption
  33. height += _portSpasing; // space below caption
  34. unsigned int inPortWidth = maxPortsTextAdvance(nodeId, PortType::In);
  35. unsigned int outPortWidth = maxPortsTextAdvance(nodeId, PortType::Out);
  36. unsigned int width = inPortWidth + outPortWidth + 4 * _portSpasing;
  37. if (auto w = _graphModel.nodeData<QWidget *>(nodeId, NodeRole::Widget)) {
  38. width += w->width();
  39. }
  40. width = std::max(width, static_cast<unsigned int>(capRect.width()) + 2 * _portSpasing);
  41. QSize size(width, height);
  42. _graphModel.setNodeData(nodeId, NodeRole::Size, size);
  43. }
  44. QPointF DefaultHorizontalNodeGeometry::portPosition(NodeId const nodeId,
  45. PortType const portType,
  46. PortIndex const portIndex) const
  47. {
  48. unsigned int const step = _portSize + _portSpasing;
  49. QPointF result;
  50. double totalHeight = 0.0;
  51. totalHeight += captionRect(nodeId).height();
  52. totalHeight += _portSpasing;
  53. totalHeight += step * portIndex;
  54. totalHeight += step / 2.0;
  55. QSize size = _graphModel.nodeData<QSize>(nodeId, NodeRole::Size);
  56. switch (portType) {
  57. case PortType::In: {
  58. double x = 0.0;
  59. result = QPointF(x, totalHeight);
  60. break;
  61. }
  62. case PortType::Out: {
  63. double x = size.width();
  64. result = QPointF(x, totalHeight);
  65. break;
  66. }
  67. default:
  68. break;
  69. }
  70. return result;
  71. }
  72. QPointF DefaultHorizontalNodeGeometry::portTextPosition(NodeId const nodeId,
  73. PortType const portType,
  74. PortIndex const portIndex) const
  75. {
  76. QPointF p = portPosition(nodeId, portType, portIndex);
  77. QRectF rect = portTextRect(nodeId, portType, portIndex);
  78. p.setY(p.y() + rect.height() / 4.0);
  79. QSize size = _graphModel.nodeData<QSize>(nodeId, NodeRole::Size);
  80. switch (portType) {
  81. case PortType::In:
  82. p.setX(_portSpasing);
  83. break;
  84. case PortType::Out:
  85. p.setX(size.width() - _portSpasing - rect.width());
  86. break;
  87. default:
  88. break;
  89. }
  90. return p;
  91. }
  92. QRectF DefaultHorizontalNodeGeometry::captionRect(NodeId const nodeId) const
  93. {
  94. if (!_graphModel.nodeData<bool>(nodeId, NodeRole::CaptionVisible))
  95. return QRect();
  96. QString name = _graphModel.nodeData<QString>(nodeId, NodeRole::Caption);
  97. return _boldFontMetrics.boundingRect(name);
  98. }
  99. QPointF DefaultHorizontalNodeGeometry::captionPosition(NodeId const nodeId) const
  100. {
  101. QSize size = _graphModel.nodeData<QSize>(nodeId, NodeRole::Size);
  102. return QPointF(0.5 * (size.width() - captionRect(nodeId).width()),
  103. 0.5 * _portSpasing + captionRect(nodeId).height());
  104. }
  105. QPointF DefaultHorizontalNodeGeometry::widgetPosition(NodeId const nodeId) const
  106. {
  107. QSize size = _graphModel.nodeData<QSize>(nodeId, NodeRole::Size);
  108. unsigned int captionHeight = captionRect(nodeId).height();
  109. if (auto w = _graphModel.nodeData<QWidget *>(nodeId, NodeRole::Widget)) {
  110. // If the widget wants to use as much vertical space as possible,
  111. // place it immediately after the caption.
  112. if (w->sizePolicy().verticalPolicy() & QSizePolicy::ExpandFlag) {
  113. return QPointF(2.0 * _portSpasing + maxPortsTextAdvance(nodeId, PortType::In),
  114. captionHeight);
  115. } else {
  116. return QPointF(2.0 * _portSpasing + maxPortsTextAdvance(nodeId, PortType::In),
  117. (captionHeight + size.height() - w->height()) / 2.0);
  118. }
  119. }
  120. return QPointF();
  121. }
  122. QRect DefaultHorizontalNodeGeometry::resizeHandleRect(NodeId const nodeId) const
  123. {
  124. QSize size = _graphModel.nodeData<QSize>(nodeId, NodeRole::Size);
  125. unsigned int rectSize = 7;
  126. return QRect(size.width() - _portSpasing, size.height() - _portSpasing, rectSize, rectSize);
  127. }
  128. QRectF DefaultHorizontalNodeGeometry::portTextRect(NodeId const nodeId,
  129. PortType const portType,
  130. PortIndex const portIndex) const
  131. {
  132. QString s;
  133. if (_graphModel.portData<bool>(nodeId, portType, portIndex, PortRole::CaptionVisible)) {
  134. s = _graphModel.portData<QString>(nodeId, portType, portIndex, PortRole::Caption);
  135. } else {
  136. auto portData = _graphModel.portData(nodeId, portType, portIndex, PortRole::DataType);
  137. s = portData.value<NodeDataType>().name;
  138. }
  139. return _fontMetrics.boundingRect(s);
  140. }
  141. unsigned int DefaultHorizontalNodeGeometry::maxVerticalPortsExtent(NodeId const nodeId) const
  142. {
  143. PortCount nInPorts = _graphModel.nodeData<PortCount>(nodeId, NodeRole::InPortCount);
  144. PortCount nOutPorts = _graphModel.nodeData<PortCount>(nodeId, NodeRole::OutPortCount);
  145. unsigned int maxNumOfEntries = std::max(nInPorts, nOutPorts);
  146. unsigned int step = _portSize + _portSpasing;
  147. return step * maxNumOfEntries;
  148. }
  149. unsigned int DefaultHorizontalNodeGeometry::maxPortsTextAdvance(NodeId const nodeId,
  150. PortType const portType) const
  151. {
  152. unsigned int width = 0;
  153. size_t const n = _graphModel
  154. .nodeData(nodeId,
  155. (portType == PortType::Out) ? NodeRole::OutPortCount
  156. : NodeRole::InPortCount)
  157. .toUInt();
  158. for (PortIndex portIndex = 0ul; portIndex < n; ++portIndex) {
  159. QString name;
  160. if (_graphModel.portData<bool>(nodeId, portType, portIndex, PortRole::CaptionVisible)) {
  161. name = _graphModel.portData<QString>(nodeId, portType, portIndex, PortRole::Caption);
  162. } else {
  163. NodeDataType portData = _graphModel.portData<NodeDataType>(nodeId,
  164. portType,
  165. portIndex,
  166. PortRole::DataType);
  167. name = portData.name;
  168. }
  169. #if QT_VERSION >= QT_VERSION_CHECK(5, 15, 0)
  170. width = std::max(unsigned(_fontMetrics.horizontalAdvance(name)), width);
  171. #else
  172. width = std::max(unsigned(_fontMetrics.width(name)), width);
  173. #endif
  174. }
  175. return width;
  176. }
  177. } // namespace QtNodes