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.

170 lines
5.5KB

  1. #pragma once
  2. #include "common.hpp"
  3. #include "math.hpp"
  4. #include "window.hpp"
  5. #include "color.hpp"
  6. #include "widget/event.hpp"
  7. #include <list>
  8. namespace rack {
  9. /** General UI widgets
  10. */
  11. namespace widget {
  12. /** A node in the 2D [scene graph](https://en.wikipedia.org/wiki/Scene_graph).
  13. The bounding box of a Widget is a rectangle specified by `box` relative to their parent.
  14. The appearance is defined by overriding `draw()`, and the behavior is defined by overriding `step()` and `on*()` event handlers.
  15. */
  16. struct Widget {
  17. /** Stores position and size */
  18. math::Rect box = math::Rect(math::Vec(), math::Vec(INFINITY, INFINITY));
  19. /** Automatically set when Widget is added as a child to another Widget */
  20. Widget *parent = NULL;
  21. std::list<Widget*> children;
  22. /** Disables rendering but allow stepping */
  23. bool visible = true;
  24. /** If set to true, parent will delete Widget in the next step() */
  25. bool requestedDelete = false;
  26. virtual ~Widget();
  27. void setPos(math::Vec pos);
  28. void setSize(math::Vec size);
  29. void show();
  30. void hide();
  31. void requestDelete();
  32. virtual math::Rect getChildrenBoundingBox();
  33. /** Returns `v` transformed into the coordinate system of `relative` */
  34. virtual math::Vec getRelativeOffset(math::Vec v, Widget *relative);
  35. /** Returns `v` transformed into world coordinates */
  36. math::Vec getAbsoluteOffset(math::Vec v) {
  37. return getRelativeOffset(v, NULL);
  38. }
  39. /** Returns a subset of the given math::Rect bounded by the box of this widget and all ancestors */
  40. virtual math::Rect getViewport(math::Rect r);
  41. template <class T>
  42. T *getAncestorOfType() {
  43. if (!parent) return NULL;
  44. T *p = dynamic_cast<T*>(parent);
  45. if (p) return p;
  46. return parent->getAncestorOfType<T>();
  47. }
  48. template <class T>
  49. T *getFirstDescendantOfType() {
  50. for (Widget *child : children) {
  51. T *c = dynamic_cast<T*>(child);
  52. if (c) return c;
  53. c = child->getFirstDescendantOfType<T>();
  54. if (c) return c;
  55. }
  56. return NULL;
  57. }
  58. /** Adds widget to list of children.
  59. Gives ownership of widget to this widget instance.
  60. */
  61. void addChild(Widget *child);
  62. /** Removes widget from list of children if it exists.
  63. Does not delete widget but transfers ownership to caller
  64. */
  65. void removeChild(Widget *child);
  66. /** Removes and deletes all children */
  67. void clearChildren();
  68. /** Advances the module by one frame */
  69. virtual void step();
  70. struct DrawArgs {
  71. NVGcontext *vg;
  72. math::Rect clipBox;
  73. NVGLUframebuffer *fb = NULL;
  74. };
  75. /** Draws the widget to the NanoVG context */
  76. virtual void draw(const DrawArgs &args);
  77. /** Override draw(const DrawArgs &args) instead */
  78. DEPRECATED virtual void draw(NVGcontext *vg) {}
  79. // Events
  80. /** Recurses an event to all visible Widgets */
  81. template <typename TMethod, class TEvent>
  82. void recurseEvent(TMethod f, const TEvent &e) {
  83. for (auto it = children.rbegin(); it != children.rend(); it++) {
  84. Widget *child = *it;
  85. // Filter child by visibility
  86. if (!child->visible)
  87. continue;
  88. // Call child event handler
  89. (child->*f)(e);
  90. }
  91. }
  92. /** Recurses an event to all visible Widgets until it is consumed. */
  93. template <typename TMethod, class TEvent>
  94. void recursePositionEvent(TMethod f, const TEvent &e) {
  95. for (auto it = children.rbegin(); it != children.rend(); it++) {
  96. Widget *child = *it;
  97. // Filter child by visibility and position
  98. if (!child->visible)
  99. continue;
  100. if (!child->box.isContaining(e.pos))
  101. continue;
  102. // Clone event and adjust its position
  103. TEvent e2 = e;
  104. e2.pos = e.pos.minus(child->box.pos);
  105. // Call child event handler
  106. (child->*f)(e2);
  107. // Stop iterating if consumed
  108. if (e.getConsumed())
  109. break;
  110. }
  111. }
  112. /** Override these event callbacks to respond to events.
  113. See events.hpp for a description of each event.
  114. */
  115. virtual void onHover(const HoverEvent &e) {recursePositionEvent(&Widget::onHover, e);}
  116. virtual void onButton(const ButtonEvent &e) {recursePositionEvent(&Widget::onButton, e);}
  117. virtual void onDoubleClick(const DoubleClickEvent &e) {}
  118. virtual void onHoverKey(const HoverKeyEvent &e) {recursePositionEvent(&Widget::onHoverKey, e);}
  119. virtual void onHoverText(const HoverTextEvent &e) {recursePositionEvent(&Widget::onHoverText, e);}
  120. virtual void onHoverScroll(const HoverScrollEvent &e) {recursePositionEvent(&Widget::onHoverScroll, e);}
  121. virtual void onEnter(const EnterEvent &e) {}
  122. virtual void onLeave(const LeaveEvent &e) {}
  123. virtual void onSelect(const SelectEvent &e) {}
  124. virtual void onDeselect(const DeselectEvent &e) {}
  125. virtual void onSelectKey(const SelectKeyEvent &e) {}
  126. virtual void onSelectText(const SelectTextEvent &e) {}
  127. virtual void onDragStart(const DragStartEvent &e) {}
  128. virtual void onDragEnd(const DragEndEvent &e) {}
  129. virtual void onDragMove(const DragMoveEvent &e) {}
  130. virtual void onDragHover(const DragHoverEvent &e) {recursePositionEvent(&Widget::onDragHover, e);}
  131. virtual void onDragEnter(const DragEnterEvent &e) {}
  132. virtual void onDragLeave(const DragLeaveEvent &e) {}
  133. virtual void onDragDrop(const DragDropEvent &e) {}
  134. virtual void onPathDrop(const PathDropEvent &e) {recursePositionEvent(&Widget::onPathDrop, e);}
  135. virtual void onAction(const ActionEvent &e) {}
  136. virtual void onChange(const ChangeEvent &e) {}
  137. virtual void onZoom(const ZoomEvent &e) {recurseEvent(&Widget::onZoom, e);}
  138. virtual void onReposition(const RepositionEvent &e) {}
  139. virtual void onResize(const ResizeEvent &e) {}
  140. virtual void onAdd(const AddEvent &e) {}
  141. virtual void onRemove(const RemoveEvent &e) {}
  142. virtual void onShow(const ShowEvent &e) {recurseEvent(&Widget::onShow, e);}
  143. virtual void onHide(const HideEvent &e) {recurseEvent(&Widget::onHide, e);}
  144. };
  145. } // namespace widget
  146. } // namespace rack