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.

131 lines
2.8KB

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