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.

281 lines
6.6KB

  1. #pragma once
  2. #include <assert.h>
  3. #include <stdio.h>
  4. #include <math.h>
  5. #include <list>
  6. #include <map>
  7. #include "../ext/nanovg/src/nanovg.h"
  8. #include "../ext/oui/blendish.h"
  9. #include "math.hpp"
  10. #include "util.hpp"
  11. namespace rack {
  12. ////////////////////
  13. // base class and traits
  14. ////////////////////
  15. /** A node in the 2D scene graph */
  16. struct Widget {
  17. /** Stores position and size */
  18. Rect box = Rect(Vec(), Vec(INFINITY, INFINITY));
  19. Widget *parent = NULL;
  20. std::list<Widget*> children;
  21. virtual ~Widget();
  22. Vec getAbsolutePos();
  23. Rect getChildrenBoundingBox();
  24. template <class T>
  25. T *getAncestorOfType() {
  26. if (!parent) return NULL;
  27. T *p = dynamic_cast<T*>(parent);
  28. if (p) return p;
  29. return parent->getAncestorOfType<T>();
  30. }
  31. /** Adds widget to list of children.
  32. Gives ownership of widget to this widget instance.
  33. */
  34. void addChild(Widget *widget);
  35. // Does not delete widget but transfers ownership to caller
  36. // Silenty fails if widget is not a child
  37. void removeChild(Widget *widget);
  38. void clearChildren();
  39. /** Advances the module by one frame */
  40. virtual void step();
  41. /** Draws to NanoVG context */
  42. virtual void draw(NVGcontext *vg);
  43. // Events
  44. /** Called when a mouse button is pressed over this widget
  45. 0 for left, 1 for right, 2 for middle.
  46. Return `this` to accept the event.
  47. Return NULL to reject the event and pass it to the widget behind this one.
  48. */
  49. virtual Widget *onMouseDown(Vec pos, int button);
  50. virtual Widget *onMouseUp(Vec pos, int button);
  51. virtual Widget *onMouseMove(Vec pos, Vec mouseRel);
  52. /** Called when this widget begins responding to `onMouseMove` events */
  53. virtual void onMouseEnter() {}
  54. /** Called when another widget begins responding to `onMouseMove` events */
  55. virtual void onMouseLeave() {}
  56. virtual Widget *onScroll(Vec pos, Vec scrollRel);
  57. /** Called when a widget responds to `onMouseDown` for a left button press */
  58. virtual void onDragStart() {}
  59. /** Called when the left button is released and this widget is being dragged */
  60. virtual void onDragEnd() {}
  61. /** Called when a widget responds to `onMouseMove` and is being dragged */
  62. virtual void onDragMove(Vec mouseRel) {}
  63. /** Called when a widget responds to `onMouseUp` for a left button release and a widget is being dragged */
  64. virtual void onDragDrop(Widget *origin) {}
  65. virtual void onAction() {}
  66. virtual void onChange() {}
  67. };
  68. /** Widget that does not respond to events */
  69. struct TransparentWidget : virtual Widget {
  70. Widget *onMouseDown(Vec pos, int button) {return NULL;}
  71. Widget *onMouseUp(Vec pos, int button) {return NULL;}
  72. Widget *onMouseMove(Vec pos, Vec mouseRel) {return NULL;}
  73. Widget *onScroll(Vec pos, Vec scrollRel) {return NULL;}
  74. };
  75. /** Widget that itself responds to mouse events */
  76. struct OpaqueWidget : virtual Widget {
  77. Widget *onMouseDown(Vec pos, int button) {
  78. Widget *w = Widget::onMouseDown(pos, button);
  79. if (w) return w;
  80. onMouseDown(button);
  81. return this;
  82. }
  83. Widget *onMouseUp(Vec pos, int button) {
  84. Widget *w = Widget::onMouseUp(pos, button);
  85. if (w) return w;
  86. onMouseUp(button);
  87. return this;
  88. }
  89. Widget *onMouseMove(Vec pos, Vec mouseRel) {
  90. Widget *w = Widget::onMouseMove(pos, mouseRel);
  91. if (w) return w;
  92. onMouseMove(mouseRel);
  93. return this;
  94. }
  95. /** "High level" events called by the above lower level events.
  96. Use these if you don't care about the clicked position.
  97. */
  98. virtual void onMouseDown(int button) {}
  99. virtual void onMouseUp(int button) {}
  100. virtual void onMouseMove(Vec mouseRel) {}
  101. };
  102. struct SpriteWidget : virtual Widget {
  103. Vec spriteOffset;
  104. Vec spriteSize;
  105. std::string spriteFilename;
  106. int index = 0;
  107. void draw(NVGcontext *vg);
  108. };
  109. struct QuantityWidget : virtual Widget {
  110. float value = 0.0;
  111. float minValue = 0.0;
  112. float maxValue = 1.0;
  113. float defaultValue = 0.0;
  114. std::string label;
  115. /** Include a space character if you want a space after the number, e.g. " Hz" */
  116. std::string unit;
  117. /** The digit place to round for displaying values.
  118. A precision of -2 will display as "1.00" for example.
  119. */
  120. int precision = -2;
  121. QuantityWidget();
  122. void setValue(float value);
  123. void setLimits(float minValue, float maxValue);
  124. void setDefaultValue(float defaultValue);
  125. /** Generates the display value */
  126. std::string getText();
  127. };
  128. ////////////////////
  129. // gui elements
  130. ////////////////////
  131. struct Label : Widget {
  132. std::string text;
  133. Label() {
  134. box.size.y = BND_WIDGET_HEIGHT;
  135. }
  136. void draw(NVGcontext *vg);
  137. };
  138. // Deletes itself from parent when clicked
  139. struct MenuOverlay : OpaqueWidget {
  140. void step();
  141. Widget *onScroll(Vec pos, Vec scrollRel) {
  142. return this;
  143. }
  144. void onDragDrop(Widget *origin);
  145. };
  146. struct Menu : OpaqueWidget {
  147. Menu() {
  148. box.size = Vec(0, 0);
  149. }
  150. // Resizes menu and calls addChild()
  151. void pushChild(Widget *child);
  152. void draw(NVGcontext *vg);
  153. };
  154. struct MenuEntry : OpaqueWidget {
  155. std::string text;
  156. MenuEntry() {
  157. box.size = Vec(0, BND_WIDGET_HEIGHT);
  158. }
  159. float computeMinWidth(NVGcontext *vg);
  160. };
  161. struct MenuLabel : MenuEntry {
  162. void draw(NVGcontext *vg);
  163. };
  164. struct MenuItem : MenuEntry {
  165. BNDwidgetState state = BND_DEFAULT;
  166. void draw(NVGcontext *vg);
  167. void onMouseEnter();
  168. void onMouseLeave() ;
  169. void onDragDrop(Widget *origin);
  170. };
  171. struct Button : OpaqueWidget {
  172. std::string text;
  173. BNDwidgetState state = BND_DEFAULT;
  174. Button() {
  175. box.size.y = BND_WIDGET_HEIGHT;
  176. }
  177. void draw(NVGcontext *vg);
  178. void onMouseEnter();
  179. void onMouseLeave();
  180. void onDragStart();
  181. void onDragEnd();
  182. void onDragDrop(Widget *origin);
  183. };
  184. struct ChoiceButton : Button {
  185. void draw(NVGcontext *vg);
  186. };
  187. struct RadioButton : OpaqueWidget, QuantityWidget {
  188. BNDwidgetState state = BND_DEFAULT;
  189. RadioButton() {
  190. box.size.y = BND_WIDGET_HEIGHT;
  191. }
  192. void draw(NVGcontext *vg);
  193. void onMouseEnter();
  194. void onMouseLeave();
  195. void onDragDrop(Widget *origin);
  196. };
  197. struct Slider : OpaqueWidget, QuantityWidget {
  198. BNDwidgetState state = BND_DEFAULT;
  199. Slider() {
  200. box.size.y = BND_WIDGET_HEIGHT;
  201. }
  202. void draw(NVGcontext *vg);
  203. void onDragStart();
  204. void onDragMove(Vec mouseRel);
  205. void onDragEnd();
  206. };
  207. struct ScrollBar : OpaqueWidget {
  208. enum { VERTICAL, HORIZONTAL } orientation;
  209. float containerOffset = 0.0;
  210. float containerSize = 0.0;
  211. BNDwidgetState state = BND_DEFAULT;
  212. ScrollBar() {
  213. box.size = Vec(BND_SCROLLBAR_WIDTH, BND_SCROLLBAR_HEIGHT);
  214. }
  215. void draw(NVGcontext *vg);
  216. void move(float delta);
  217. void onDragStart();
  218. void onDragMove(Vec mouseRel);
  219. void onDragEnd();
  220. };
  221. // Handles a container with scrollbars
  222. struct ScrollWidget : OpaqueWidget {
  223. Widget *container;
  224. ScrollBar *hScrollBar;
  225. ScrollBar *vScrollBar;
  226. ScrollWidget();
  227. void step();
  228. void draw(NVGcontext *vg);
  229. Widget *onScroll(Vec pos, Vec scrollRel);
  230. };
  231. struct Tooltip : Widget {
  232. void step();
  233. void draw(NVGcontext *vg);
  234. };
  235. } // namespace rack