You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

139 lines
3.0KB

  1. #include "widgets.hpp"
  2. #include <algorithm>
  3. namespace rack {
  4. Widget::~Widget() {
  5. // You should only delete orphaned widgets
  6. assert(!parent);
  7. // Stop dragging and hovering this widget
  8. if (gHoveredWidget == this) gHoveredWidget = NULL;
  9. if (gDraggedWidget == this) gDraggedWidget = NULL;
  10. if (gDragHoveredWidget == this) gDragHoveredWidget = NULL;
  11. if (gSelectedWidget == this) gSelectedWidget = NULL;
  12. clearChildren();
  13. }
  14. Vec Widget::getAbsolutePos() {
  15. // Recursively compute position offset from parents
  16. if (!parent) {
  17. return box.pos;
  18. }
  19. else {
  20. return box.pos.plus(parent->getAbsolutePos());
  21. }
  22. }
  23. Rect Widget::getChildrenBoundingBox() {
  24. if (children.empty()) {
  25. return Rect();
  26. }
  27. Vec topLeft = Vec(INFINITY, INFINITY);
  28. Vec bottomRight = Vec(-INFINITY, -INFINITY);
  29. for (Widget *child : children) {
  30. topLeft = topLeft.min(child->box.pos);
  31. bottomRight = bottomRight.max(child->box.getBottomRight());
  32. }
  33. return Rect(topLeft, bottomRight.minus(topLeft));
  34. }
  35. void Widget::addChild(Widget *widget) {
  36. assert(!widget->parent);
  37. widget->parent = this;
  38. children.push_back(widget);
  39. }
  40. void Widget::removeChild(Widget *widget) {
  41. assert(widget->parent == this);
  42. auto it = std::find(children.begin(), children.end(), widget);
  43. if (it != children.end()) {
  44. children.erase(it);
  45. widget->parent = NULL;
  46. }
  47. }
  48. void Widget::clearChildren() {
  49. for (Widget *child : children) {
  50. child->parent = NULL;
  51. delete child;
  52. }
  53. children.clear();
  54. }
  55. void Widget::step() {
  56. for (Widget *child : children) {
  57. child->step();
  58. }
  59. }
  60. void Widget::draw(NVGcontext *vg) {
  61. for (Widget *child : children) {
  62. if (!child->visible)
  63. continue;
  64. nvgSave(vg);
  65. nvgTranslate(vg, child->box.pos.x, child->box.pos.y);
  66. child->draw(vg);
  67. nvgRestore(vg);
  68. }
  69. }
  70. Widget *Widget::onMouseDown(Vec pos, int button) {
  71. for (auto it = children.rbegin(); it != children.rend(); it++) {
  72. Widget *child = *it;
  73. if (!child->visible)
  74. continue;
  75. if (child->box.contains(pos)) {
  76. Widget *w = child->onMouseDown(pos.minus(child->box.pos), button);
  77. if (w)
  78. return w;
  79. }
  80. }
  81. return NULL;
  82. }
  83. Widget *Widget::onMouseUp(Vec pos, int button) {
  84. for (auto it = children.rbegin(); it != children.rend(); it++) {
  85. Widget *child = *it;
  86. if (!child->visible)
  87. continue;
  88. if (child->box.contains(pos)) {
  89. Widget *w = child->onMouseUp(pos.minus(child->box.pos), button);
  90. if (w)
  91. return w;
  92. }
  93. }
  94. return NULL;
  95. }
  96. Widget *Widget::onMouseMove(Vec pos, Vec mouseRel) {
  97. for (auto it = children.rbegin(); it != children.rend(); it++) {
  98. Widget *child = *it;
  99. if (!child->visible)
  100. continue;
  101. if (child->box.contains(pos)) {
  102. Widget *w = child->onMouseMove(pos.minus(child->box.pos), mouseRel);
  103. if (w)
  104. return w;
  105. }
  106. }
  107. return NULL;
  108. }
  109. Widget *Widget::onScroll(Vec pos, Vec scrollRel) {
  110. for (auto it = children.rbegin(); it != children.rend(); it++) {
  111. Widget *child = *it;
  112. if (!child->visible)
  113. continue;
  114. if (child->box.contains(pos)) {
  115. Widget *w = child->onScroll(pos.minus(child->box.pos), scrollRel);
  116. if (w)
  117. return w;
  118. }
  119. }
  120. return NULL;
  121. }
  122. } // namespace rack