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.

147 lines
4.7KB

  1. #pragma once
  2. #include "common.hpp"
  3. #include "math.hpp"
  4. #include "window.hpp"
  5. #include "color.hpp"
  6. #include "event.hpp"
  7. #include <list>
  8. namespace rack {
  9. struct DrawContext {
  10. mutable NVGcontext *vg;
  11. };
  12. /** A node in the 2D scene graph
  13. */
  14. struct Widget {
  15. /** Stores position and size */
  16. math::Rect box = math::Rect(math::Vec(), math::Vec(INFINITY, INFINITY));
  17. /** Automatically set when Widget is added as a child to another Widget */
  18. Widget *parent = NULL;
  19. std::list<Widget*> children;
  20. /** Disables rendering but allow stepping */
  21. bool visible = true;
  22. /** If set to true, parent will delete Widget in the next step() */
  23. bool requestedDelete = false;
  24. virtual ~Widget();
  25. virtual math::Rect getChildrenBoundingBox();
  26. /** Returns `v` transformed into the coordinate system of `relative` */
  27. virtual math::Vec getRelativeOffset(math::Vec v, Widget *relative);
  28. /** Returns `v` transformed into world coordinates */
  29. math::Vec getAbsoluteOffset(math::Vec v) {
  30. return getRelativeOffset(v, NULL);
  31. }
  32. /** Returns a subset of the given math::Rect bounded by the box of this widget and all ancestors */
  33. virtual math::Rect getViewport(math::Rect r);
  34. template <class T>
  35. T *getAncestorOfType() {
  36. if (!parent) return NULL;
  37. T *p = dynamic_cast<T*>(parent);
  38. if (p) return p;
  39. return parent->getAncestorOfType<T>();
  40. }
  41. template <class T>
  42. T *getFirstDescendantOfType() {
  43. for (Widget *child : children) {
  44. T *c = dynamic_cast<T*>(child);
  45. if (c) return c;
  46. c = child->getFirstDescendantOfType<T>();
  47. if (c) return c;
  48. }
  49. return NULL;
  50. }
  51. /** Adds widget to list of children.
  52. Gives ownership of widget to this widget instance.
  53. */
  54. void addChild(Widget *child);
  55. /** Removes widget from list of children if it exists.
  56. Does not delete widget but transfers ownership to caller
  57. */
  58. void removeChild(Widget *child);
  59. /** Removes and deletes all children */
  60. void clearChildren();
  61. /** Advances the module by one frame */
  62. virtual void step();
  63. /** Draws the widget to the NanoVG context */
  64. virtual void draw(const DrawContext &ctx);
  65. /** Override `draw(const DrawContext &ctx)` instead */
  66. DEPRECATED virtual void draw(NVGcontext *vg) {}
  67. // Events
  68. /** Recurses an event to all visible Widgets */
  69. template <typename TMethod, class TEvent>
  70. void recurseEvent(TMethod f, const TEvent &e) {
  71. for (auto it = children.rbegin(); it != children.rend(); it++) {
  72. Widget *child = *it;
  73. // Filter child by visibility
  74. if (!child->visible)
  75. continue;
  76. // Call child event handler
  77. (child->*f)(e);
  78. }
  79. }
  80. /** Recurses an event to all visible Widgets until it is consumed. */
  81. template <typename TMethod, class TEvent>
  82. void recursePositionEvent(TMethod f, const TEvent &e) {
  83. for (auto it = children.rbegin(); it != children.rend(); it++) {
  84. Widget *child = *it;
  85. // Filter child by visibility and position
  86. if (!child->visible)
  87. continue;
  88. if (!child->box.contains(e.pos))
  89. continue;
  90. // Clone event and adjust its position
  91. TEvent e2 = e;
  92. e2.pos = e.pos.minus(child->box.pos);
  93. // Call child event handler
  94. (child->*f)(e2);
  95. // Stop iterating if consumed
  96. if (e.getConsumed())
  97. break;
  98. }
  99. }
  100. /** Override these event callbacks to respond to events.
  101. See events.hpp for a description of each event.
  102. */
  103. virtual void onHover(const event::Hover &e) {recursePositionEvent(&Widget::onHover, e);}
  104. virtual void onButton(const event::Button &e) {recursePositionEvent(&Widget::onButton, e);}
  105. virtual void onHoverKey(const event::HoverKey &e) {recursePositionEvent(&Widget::onHoverKey, e);}
  106. virtual void onHoverText(const event::HoverText &e) {recursePositionEvent(&Widget::onHoverText, e);}
  107. virtual void onHoverScroll(const event::HoverScroll &e) {recursePositionEvent(&Widget::onHoverScroll, e);}
  108. virtual void onEnter(const event::Enter &e) {}
  109. virtual void onLeave(const event::Leave &e) {}
  110. virtual void onSelect(const event::Select &e) {}
  111. virtual void onDeselect(const event::Deselect &e) {}
  112. virtual void onSelectKey(const event::SelectKey &e) {}
  113. virtual void onSelectText(const event::SelectText &e) {}
  114. virtual void onDragStart(const event::DragStart &e) {}
  115. virtual void onDragEnd(const event::DragEnd &e) {}
  116. virtual void onDragMove(const event::DragMove &e) {}
  117. virtual void onDragHover(const event::DragHover &e) {recursePositionEvent(&Widget::onDragHover, e);}
  118. virtual void onDragEnter(const event::DragEnter &e) {}
  119. virtual void onDragLeave(const event::DragLeave &e) {}
  120. virtual void onDragDrop(const event::DragDrop &e) {}
  121. virtual void onPathDrop(const event::PathDrop &e) {recursePositionEvent(&Widget::onPathDrop, e);}
  122. virtual void onAction(const event::Action &e) {}
  123. virtual void onChange(const event::Change &e) {}
  124. virtual void onZoom(const event::Zoom &e) {recurseEvent(&Widget::onZoom, e);}
  125. };
  126. } // namespace rack