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.

129 lines
4.6KB

  1. #pragma once
  2. #include "window.hpp"
  3. namespace rack {
  4. /** A node in the 2D scene graph
  5. Never inherit from Widget directly. Instead, inherit from VirtualWidget declared below.
  6. */
  7. struct Widget {
  8. /** Stores position and size */
  9. math::Rect box = math::Rect(math::Vec(), math::Vec(INFINITY, INFINITY));
  10. Widget *parent = NULL;
  11. std::list<Widget*> children;
  12. bool visible = true;
  13. virtual ~Widget();
  14. virtual math::Rect getChildrenBoundingBox();
  15. /** Returns `v` transformed into the coordinate system of `relative` */
  16. virtual math::Vec getRelativeOffset(math::Vec v, Widget *relative);
  17. /** Returns `v` transformed into world coordinates */
  18. math::Vec getAbsoluteOffset(math::Vec v) {
  19. return getRelativeOffset(v, NULL);
  20. }
  21. /** Returns a subset of the given math::Rect bounded by the box of this widget and all ancestors */
  22. virtual math::Rect getViewport(math::Rect r);
  23. template <class T>
  24. T *getAncestorOfType() {
  25. if (!parent) return NULL;
  26. T *p = dynamic_cast<T*>(parent);
  27. if (p) return p;
  28. return parent->getAncestorOfType<T>();
  29. }
  30. template <class T>
  31. T *getFirstDescendantOfType() {
  32. for (Widget *child : children) {
  33. T *c = dynamic_cast<T*>(child);
  34. if (c) return c;
  35. c = child->getFirstDescendantOfType<T>();
  36. if (c) return c;
  37. }
  38. return NULL;
  39. }
  40. /** Adds widget to list of children.
  41. Gives ownership of widget to this widget instance.
  42. */
  43. void addChild(Widget *widget);
  44. /** Removes widget from list of children if it exists.
  45. Does not delete widget but transfers ownership to caller
  46. */
  47. void removeChild(Widget *widget);
  48. /** Removes and deletes all children */
  49. void clearChildren();
  50. /** Recursively finalizes event start/end pairs as needed */
  51. void finalizeEvents();
  52. /** Advances the module by one frame */
  53. virtual void step();
  54. /** Draws to NanoVG context */
  55. virtual void draw(NVGcontext *vg);
  56. // Events
  57. /** Called when a mouse button is pressed over this widget */
  58. virtual void onMouseDown(EventMouseDown &e);
  59. /** Called when a mouse button is released over this widget */
  60. virtual void onMouseUp(EventMouseUp &e);
  61. /** Called when the mouse moves over this widget.
  62. Called on every frame, even if `mouseRel = math::Vec(0, 0)`.
  63. */
  64. virtual void onMouseMove(EventMouseMove &e);
  65. /** Called when a key is pressed while hovering over this widget */
  66. virtual void onHoverKey(EventHoverKey &e);
  67. /** Called when this widget begins responding to `onMouseMove` events */
  68. virtual void onMouseEnter(EventMouseEnter &e) {}
  69. /** Called when this widget no longer responds to `onMouseMove` events */
  70. virtual void onMouseLeave(EventMouseLeave &e) {}
  71. /** Called when this widget gains focus by responding to the `onMouseDown` event */
  72. virtual void onFocus(EventFocus &e) {}
  73. virtual void onDefocus(EventDefocus &e) {}
  74. /** Called when a printable character is received while this widget is focused */
  75. virtual void onText(EventText &e) {}
  76. /** Called when a key is pressed while this widget is focused */
  77. virtual void onKey(EventKey &e) {}
  78. /** Called when the scroll wheel is moved while the mouse is hovering over this widget */
  79. virtual void onScroll(EventScroll &e);
  80. /** Called when a widget responds to `onMouseDown` for a left button press */
  81. virtual void onDragStart(EventDragStart &e) {}
  82. /** Called when the left button is released and this widget is being dragged */
  83. virtual void onDragEnd(EventDragEnd &e) {}
  84. /** Called when a widget responds to `onMouseMove` and is being dragged */
  85. virtual void onDragMove(EventDragMove &e) {}
  86. /** Called when a widget responds to `onMouseUp` for a left button release and a widget is being dragged */
  87. virtual void onDragEnter(EventDragEnter &e) {}
  88. virtual void onDragLeave(EventDragEnter &e) {}
  89. /** Called when a drag action ends while hovering this widget */
  90. virtual void onDragDrop(EventDragDrop &e) {}
  91. /** Called when an OS selection of files is dragged-and-dropped on this widget */
  92. virtual void onPathDrop(EventPathDrop &e);
  93. /** Called when an event triggers an action */
  94. virtual void onAction(EventAction &e) {}
  95. /** For widgets with some concept of values, called when the value is changed */
  96. virtual void onChange(EventChange &e) {}
  97. /** Called when the zoom level is changed of this widget */
  98. virtual void onZoom(EventZoom &e);
  99. /** Helper function for creating and initializing a Widget with certain arguments (in this case just the position).
  100. In this project, you will find this idiom everywhere, as an easier alternative to constructor arguments, for building a Widget (or a subclass) with a one-liner.
  101. Example:
  102. addChild(Widget::create<SVGWidget>(math::Vec(10, 10)))
  103. */
  104. template <typename T = Widget>
  105. static T *create(math::Vec pos = math::Vec()) {
  106. T *o = new T();
  107. o->box.pos = pos;
  108. return o;
  109. }
  110. };
  111. } // namespace rack