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.

140 lines
4.5KB

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