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.

135 lines
4.2KB

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