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.

208 lines
4.3KB

  1. #include "widgets.hpp"
  2. #include "app.hpp"
  3. #include <algorithm>
  4. namespace rack {
  5. Widget::~Widget() {
  6. // You should only delete orphaned widgets
  7. assert(!parent);
  8. // Stop dragging and hovering this widget
  9. if (gHoveredWidget == this) gHoveredWidget = NULL;
  10. if (gDraggedWidget == this) gDraggedWidget = NULL;
  11. if (gDragHoveredWidget == this) gDragHoveredWidget = NULL;
  12. if (gFocusedWidget == this) gFocusedWidget = NULL;
  13. clearChildren();
  14. }
  15. Rect Widget::getChildrenBoundingBox() {
  16. Rect bound;
  17. for (Widget *child : children) {
  18. if (child == children.front()) {
  19. bound = child->box;
  20. }
  21. else {
  22. bound = bound.expand(child->box);
  23. }
  24. }
  25. return bound;
  26. }
  27. Vec Widget::getRelativeOffset(Vec v, Widget *relative) {
  28. if (this == relative) {
  29. return v;
  30. }
  31. v = v.plus(box.pos);
  32. if (parent) {
  33. v = parent->getRelativeOffset(v, relative);
  34. }
  35. return v;
  36. }
  37. Rect Widget::getViewport(Rect r) {
  38. Rect bound;
  39. if (parent) {
  40. bound = parent->getViewport(box);
  41. }
  42. else {
  43. bound = box;
  44. }
  45. bound.pos = bound.pos.minus(box.pos);
  46. return r.clamp(bound);
  47. }
  48. void Widget::addChild(Widget *widget) {
  49. assert(!widget->parent);
  50. widget->parent = this;
  51. children.push_back(widget);
  52. }
  53. void Widget::removeChild(Widget *widget) {
  54. assert(widget->parent == this);
  55. auto it = std::find(children.begin(), children.end(), widget);
  56. if (it != children.end()) {
  57. children.erase(it);
  58. widget->parent = NULL;
  59. }
  60. }
  61. void Widget::clearChildren() {
  62. for (Widget *child : children) {
  63. child->parent = NULL;
  64. delete child;
  65. }
  66. children.clear();
  67. }
  68. void Widget::finalizeEvents() {
  69. // Stop dragging and hovering this widget
  70. if (gHoveredWidget == this) {
  71. gHoveredWidget->onMouseLeave();
  72. gHoveredWidget = NULL;
  73. }
  74. if (gDraggedWidget == this) {
  75. gDraggedWidget->onDragEnd();
  76. gDraggedWidget = NULL;
  77. }
  78. if (gDragHoveredWidget == this) {
  79. gDragHoveredWidget = NULL;
  80. }
  81. if (gFocusedWidget == this) {
  82. gFocusedWidget->onDefocus();
  83. gFocusedWidget = NULL;
  84. }
  85. for (Widget *child : children) {
  86. child->finalizeEvents();
  87. }
  88. }
  89. void Widget::step() {
  90. for (Widget *child : children) {
  91. child->step();
  92. }
  93. }
  94. void Widget::draw(NVGcontext *vg) {
  95. for (Widget *child : children) {
  96. if (!child->visible)
  97. continue;
  98. nvgSave(vg);
  99. nvgTranslate(vg, child->box.pos.x, child->box.pos.y);
  100. child->draw(vg);
  101. nvgRestore(vg);
  102. }
  103. }
  104. Widget *Widget::onMouseDown(Vec pos, int button) {
  105. for (auto it = children.rbegin(); it != children.rend(); it++) {
  106. Widget *child = *it;
  107. if (!child->visible)
  108. continue;
  109. if (child->box.contains(pos)) {
  110. Widget *w = child->onMouseDown(pos.minus(child->box.pos), button);
  111. if (w)
  112. return w;
  113. }
  114. }
  115. return NULL;
  116. }
  117. Widget *Widget::onMouseUp(Vec pos, int button) {
  118. for (auto it = children.rbegin(); it != children.rend(); it++) {
  119. Widget *child = *it;
  120. if (!child->visible)
  121. continue;
  122. if (child->box.contains(pos)) {
  123. Widget *w = child->onMouseUp(pos.minus(child->box.pos), button);
  124. if (w)
  125. return w;
  126. }
  127. }
  128. return NULL;
  129. }
  130. Widget *Widget::onMouseMove(Vec pos, Vec mouseRel) {
  131. for (auto it = children.rbegin(); it != children.rend(); it++) {
  132. Widget *child = *it;
  133. if (!child->visible)
  134. continue;
  135. if (child->box.contains(pos)) {
  136. Widget *w = child->onMouseMove(pos.minus(child->box.pos), mouseRel);
  137. if (w)
  138. return w;
  139. }
  140. }
  141. return NULL;
  142. }
  143. Widget *Widget::onHoverKey(Vec pos, int key) {
  144. for (auto it = children.rbegin(); it != children.rend(); it++) {
  145. Widget *child = *it;
  146. if (!child->visible)
  147. continue;
  148. if (child->box.contains(pos)) {
  149. Widget *w = child->onHoverKey(pos.minus(child->box.pos), key);
  150. if (w)
  151. return w;
  152. }
  153. }
  154. return NULL;
  155. }
  156. Widget *Widget::onScroll(Vec pos, Vec scrollRel) {
  157. for (auto it = children.rbegin(); it != children.rend(); it++) {
  158. Widget *child = *it;
  159. if (!child->visible)
  160. continue;
  161. if (child->box.contains(pos)) {
  162. Widget *w = child->onScroll(pos.minus(child->box.pos), scrollRel);
  163. if (w)
  164. return w;
  165. }
  166. }
  167. return NULL;
  168. }
  169. bool Widget::onPathDrop(Vec pos, const std::list<std::string>& paths) {
  170. for (auto it = children.rbegin(); it != children.rend(); it++) {
  171. Widget *child = *it;
  172. if (!child->visible)
  173. continue;
  174. if (child->box.contains(pos)) {
  175. if (child->onPathDrop(pos.minus(child->box.pos), paths));
  176. return true;
  177. }
  178. }
  179. return false;
  180. }
  181. void Widget::onZoom() {
  182. for (auto it = children.rbegin(); it != children.rend(); it++) {
  183. Widget *child = *it;
  184. child->onZoom();
  185. }
  186. }
  187. } // namespace rack