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.

117 lines
2.2KB

  1. #include "widgets/Widget.hpp"
  2. #include "event.hpp"
  3. #include "context.hpp"
  4. #include <algorithm>
  5. namespace rack {
  6. Widget::~Widget() {
  7. // You should only delete orphaned widgets
  8. assert(!parent);
  9. context()->event->finalizeWidget(this);
  10. clearChildren();
  11. }
  12. math::Rect Widget::getChildrenBoundingBox() {
  13. math::Rect bound;
  14. for (Widget *child : children) {
  15. if (child == children.front()) {
  16. bound = child->box;
  17. }
  18. else {
  19. bound = bound.expand(child->box);
  20. }
  21. }
  22. return bound;
  23. }
  24. math::Vec Widget::getRelativeOffset(math::Vec v, Widget *relative) {
  25. if (this == relative) {
  26. return v;
  27. }
  28. v = v.plus(box.pos);
  29. if (parent) {
  30. v = parent->getRelativeOffset(v, relative);
  31. }
  32. return v;
  33. }
  34. math::Rect Widget::getViewport(math::Rect r) {
  35. math::Rect bound;
  36. if (parent) {
  37. bound = parent->getViewport(box);
  38. }
  39. else {
  40. bound = box;
  41. }
  42. bound.pos = bound.pos.minus(box.pos);
  43. return r.clamp(bound);
  44. }
  45. void Widget::addChild(Widget *widget) {
  46. assert(!widget->parent);
  47. widget->parent = this;
  48. children.push_back(widget);
  49. }
  50. void Widget::removeChild(Widget *widget) {
  51. assert(widget->parent == this);
  52. auto it = std::find(children.begin(), children.end(), widget);
  53. assert(it != children.end());
  54. children.erase(it);
  55. widget->parent = NULL;
  56. }
  57. void Widget::clearChildren() {
  58. for (Widget *child : children) {
  59. child->parent = NULL;
  60. delete child;
  61. }
  62. children.clear();
  63. }
  64. void Widget::step() {
  65. for (auto it = children.begin(); it != children.end();) {
  66. Widget *child = *it;
  67. // Delete children if a delete is requested
  68. if (child->requestedDelete) {
  69. it = children.erase(it);
  70. child->parent = NULL;
  71. delete child;
  72. continue;
  73. }
  74. child->step();
  75. it++;
  76. }
  77. }
  78. void Widget::draw(NVGcontext *vg) {
  79. for (Widget *child : children) {
  80. // Don't draw if invisible
  81. if (!child->visible)
  82. continue;
  83. // Don't draw if child is outside bounding box
  84. if (!box.zeroPos().intersects(child->box))
  85. continue;
  86. nvgSave(vg);
  87. nvgTranslate(vg, child->box.pos.x, child->box.pos.y);
  88. child->draw(vg);
  89. // Draw red hitboxes
  90. // if (context()->event->hoveredWidget == child) {
  91. // nvgBeginPath(vg);
  92. // nvgRect(vg, 0, 0, child->box.size.x, child->box.size.y);
  93. // nvgFillColor(vg, nvgRGBAf(1, 0, 0, 0.5));
  94. // nvgFill(vg);
  95. // }
  96. nvgRestore(vg);
  97. }
  98. }
  99. } // namespace rack