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.

441 lines
11KB

  1. #pragma once
  2. #include <list>
  3. #include <memory>
  4. #include "../ext/nanovg/src/nanovg.h"
  5. #include "../ext/oui-blendish/blendish.h"
  6. #include "../ext/nanosvg/src/nanosvg.h"
  7. #include "math.hpp"
  8. #include "util.hpp"
  9. namespace rack {
  10. ////////////////////
  11. // resources
  12. ////////////////////
  13. // Constructing these directly will load from the disk each time. Use the load() functions to load from disk and cache them as long as the shared_ptr is held.
  14. // Implemented in gui.cpp
  15. struct Font {
  16. int handle;
  17. Font(const std::string &filename);
  18. ~Font();
  19. static std::shared_ptr<Font> load(const std::string &filename);
  20. };
  21. struct Image {
  22. int handle;
  23. Image(const std::string &filename);
  24. ~Image();
  25. static std::shared_ptr<Image> load(const std::string &filename);
  26. };
  27. struct SVG {
  28. NSVGimage *handle;
  29. SVG(const std::string &filename);
  30. ~SVG();
  31. static std::shared_ptr<SVG> load(const std::string &filename);
  32. };
  33. ////////////////////
  34. // Base widget
  35. ////////////////////
  36. /** A node in the 2D scene graph */
  37. struct Widget {
  38. /** Stores position and size */
  39. Rect box = Rect(Vec(), Vec(INFINITY, INFINITY));
  40. Widget *parent = NULL;
  41. std::list<Widget*> children;
  42. bool visible = true;
  43. virtual ~Widget();
  44. Vec getAbsolutePos();
  45. Rect getChildrenBoundingBox();
  46. template <class T>
  47. T *getAncestorOfType() {
  48. if (!parent) return NULL;
  49. T *p = dynamic_cast<T*>(parent);
  50. if (p) return p;
  51. return parent->getAncestorOfType<T>();
  52. }
  53. /** Adds widget to list of children.
  54. Gives ownership of widget to this widget instance.
  55. */
  56. void addChild(Widget *widget);
  57. /** Removes widget from list of children if it exists.
  58. Does not delete widget but transfers ownership to caller
  59. Silently fails if widget is not a child
  60. */
  61. void removeChild(Widget *widget);
  62. void clearChildren();
  63. /** Recursively finalizes event start/end pairs as needed */
  64. void finalizeEvents();
  65. /** Advances the module by one frame */
  66. virtual void step();
  67. /** Draws to NanoVG context */
  68. virtual void draw(NVGcontext *vg);
  69. // Events
  70. /** Called when a mouse button is pressed over this widget
  71. 0 for left, 1 for right, 2 for middle.
  72. Return `this` to accept the event.
  73. Return NULL to reject the event and pass it to the widget behind this one.
  74. */
  75. virtual Widget *onMouseDown(Vec pos, int button);
  76. virtual Widget *onMouseUp(Vec pos, int button);
  77. /** Called on every frame, even if mouseRel = Vec(0, 0) */
  78. virtual Widget *onMouseMove(Vec pos, Vec mouseRel);
  79. virtual Widget *onHoverKey(Vec pos, int key);
  80. /** Called when this widget begins responding to `onMouseMove` events */
  81. virtual void onMouseEnter() {}
  82. /** Called when another widget begins responding to `onMouseMove` events */
  83. virtual void onMouseLeave() {}
  84. virtual void onFocus() {}
  85. virtual void onDefocus() {}
  86. virtual bool onFocusText(int codepoint) {return false;}
  87. virtual bool onFocusKey(int key) {return false;}
  88. virtual Widget *onScroll(Vec pos, Vec scrollRel);
  89. /** Called when a widget responds to `onMouseDown` for a left button press */
  90. virtual void onDragStart() {}
  91. /** Called when the left button is released and this widget is being dragged */
  92. virtual void onDragEnd() {}
  93. /** Called when a widget responds to `onMouseMove` and is being dragged */
  94. virtual void onDragMove(Vec mouseRel) {}
  95. /** Called when a widget responds to `onMouseUp` for a left button release and a widget is being dragged */
  96. virtual void onDragEnter(Widget *origin) {}
  97. virtual void onDragLeave(Widget *origin) {}
  98. virtual void onDragDrop(Widget *origin) {}
  99. virtual void onAction() {}
  100. virtual void onChange() {}
  101. };
  102. struct TransformWidget : Widget {
  103. /** The transformation matrix */
  104. float transform[6];
  105. TransformWidget();
  106. void identity();
  107. void translate(Vec delta);
  108. void rotate(float angle);
  109. void scale(Vec s);
  110. void draw(NVGcontext *vg);
  111. };
  112. ////////////////////
  113. // Trait widgets
  114. ////////////////////
  115. /** Widget that does not respond to events */
  116. struct TransparentWidget : virtual Widget {
  117. Widget *onMouseDown(Vec pos, int button) {return NULL;}
  118. Widget *onMouseUp(Vec pos, int button) {return NULL;}
  119. Widget *onMouseMove(Vec pos, Vec mouseRel) {return NULL;}
  120. Widget *onScroll(Vec pos, Vec scrollRel) {return NULL;}
  121. };
  122. /** Widget that automatically responds to all mouse events but gives a chance for children to respond instead */
  123. struct OpaqueWidget : virtual Widget {
  124. Widget *onMouseDown(Vec pos, int button) {
  125. Widget *w = Widget::onMouseDown(pos, button);
  126. if (w) return w;
  127. onMouseDownOpaque(button);
  128. return this;
  129. }
  130. Widget *onMouseUp(Vec pos, int button) {
  131. Widget *w = Widget::onMouseUp(pos, button);
  132. if (w) return w;
  133. onMouseUpOpaque(button);
  134. return this;
  135. }
  136. Widget *onMouseMove(Vec pos, Vec mouseRel) {
  137. Widget *w = Widget::onMouseMove(pos, mouseRel);
  138. if (w) return w;
  139. onMouseMoveOpaque(mouseRel);
  140. return this;
  141. }
  142. Widget *onScroll(Vec pos, Vec scrollRel) {
  143. Widget *w = Widget::onScroll(pos, scrollRel);
  144. if (w) return w;
  145. if (onScrollOpaque(scrollRel))
  146. return this;
  147. return NULL;
  148. }
  149. /** "High level" events called by the above lower level events.
  150. Use these if you don't care about the clicked position.
  151. */
  152. virtual void onMouseDownOpaque(int button) {}
  153. virtual void onMouseUpOpaque(int button) {}
  154. virtual void onMouseMoveOpaque(Vec mouseRel) {}
  155. virtual bool onScrollOpaque(Vec scrollRel) {return false;}
  156. };
  157. struct SpriteWidget : virtual Widget {
  158. Vec spriteOffset;
  159. Vec spriteSize;
  160. std::shared_ptr<Image> spriteImage;
  161. int index = 0;
  162. void draw(NVGcontext *vg);
  163. };
  164. struct SVGWidget : virtual Widget {
  165. std::shared_ptr<SVG> svg;
  166. /** Sets the box size to the svg image size */
  167. void wrap();
  168. void draw(NVGcontext *vg);
  169. };
  170. /** Caches a widget's draw() result to a framebuffer so it is called less frequently
  171. When `dirty` is true, its children will be re-rendered on the next call to step().
  172. Events are not passed to the underlying scene.
  173. */
  174. struct FramebufferWidget : virtual Widget {
  175. /** Set this to true to re-render the children to the framebuffer in the next step() */
  176. bool dirty = true;
  177. /** A margin in pixels around the children in the framebuffer
  178. This prevents cutting the rendered SVG off on the box edges.
  179. */
  180. float oversample = 2.0;
  181. /** The root object in the framebuffer scene
  182. The FramebufferWidget owns the pointer
  183. */
  184. struct Internal;
  185. Internal *internal;
  186. FramebufferWidget();
  187. ~FramebufferWidget();
  188. void step();
  189. void draw(NVGcontext *vg);
  190. int getImageHandle();
  191. };
  192. struct QuantityWidget : virtual Widget {
  193. float value = 0.0;
  194. float minValue = 0.0;
  195. float maxValue = 1.0;
  196. float defaultValue = 0.0;
  197. std::string label;
  198. /** Include a space character if you want a space after the number, e.g. " Hz" */
  199. std::string unit;
  200. /** The decimal place to round for displaying values.
  201. A precision of 2 will display as "1.00" for example.
  202. */
  203. int precision = 2;
  204. QuantityWidget();
  205. void setValue(float value);
  206. void setLimits(float minValue, float maxValue);
  207. void setDefaultValue(float defaultValue);
  208. /** Generates the display value */
  209. std::string getText();
  210. };
  211. ////////////////////
  212. // GUI widgets
  213. ////////////////////
  214. struct Label : Widget {
  215. std::string text;
  216. Label() {
  217. box.size.y = BND_WIDGET_HEIGHT;
  218. }
  219. void draw(NVGcontext *vg);
  220. };
  221. // Deletes itself from parent when clicked
  222. struct MenuOverlay : OpaqueWidget {
  223. void onDragDrop(Widget *origin);
  224. bool onScrollOpaque(Vec scrollRel) {return true;}
  225. Widget *onHoverKey(Vec pos, int key);
  226. };
  227. struct Menu : OpaqueWidget {
  228. Menu *parentMenu = NULL;
  229. Menu *childMenu = NULL;
  230. Menu() {
  231. box.size = Vec(0, 0);
  232. }
  233. ~Menu();
  234. // Resizes menu and calls addChild()
  235. void pushChild(Widget *child);
  236. void setChildMenu(Menu *menu);
  237. void fit();
  238. void step();
  239. void draw(NVGcontext *vg);
  240. bool onScrollOpaque(Vec scrollRel);
  241. };
  242. struct MenuEntry : OpaqueWidget {
  243. std::string text;
  244. std::string rightText;
  245. MenuEntry() {
  246. box.size = Vec(0, BND_WIDGET_HEIGHT);
  247. }
  248. virtual float computeMinWidth(NVGcontext *vg);
  249. };
  250. struct MenuLabel : MenuEntry {
  251. void draw(NVGcontext *vg);
  252. };
  253. struct MenuItem : MenuEntry {
  254. BNDwidgetState state = BND_DEFAULT;
  255. float computeMinWidth(NVGcontext *vg);
  256. void draw(NVGcontext *vg);
  257. virtual Menu *createChildMenu() {return NULL;}
  258. void onMouseEnter();
  259. void onMouseLeave();
  260. void onDragDrop(Widget *origin);
  261. };
  262. struct Button : OpaqueWidget {
  263. std::string text;
  264. BNDwidgetState state = BND_DEFAULT;
  265. Button() {
  266. box.size.y = BND_WIDGET_HEIGHT;
  267. }
  268. void draw(NVGcontext *vg);
  269. void onMouseEnter();
  270. void onMouseLeave();
  271. void onDragStart();
  272. void onDragEnd();
  273. void onDragDrop(Widget *origin);
  274. };
  275. struct ChoiceButton : Button {
  276. void draw(NVGcontext *vg);
  277. };
  278. struct RadioButton : OpaqueWidget, QuantityWidget {
  279. BNDwidgetState state = BND_DEFAULT;
  280. RadioButton() {
  281. box.size.y = BND_WIDGET_HEIGHT;
  282. }
  283. void draw(NVGcontext *vg);
  284. void onMouseEnter();
  285. void onMouseLeave();
  286. void onDragDrop(Widget *origin);
  287. };
  288. struct Slider : OpaqueWidget, QuantityWidget {
  289. BNDwidgetState state = BND_DEFAULT;
  290. Slider() {
  291. box.size.y = BND_WIDGET_HEIGHT;
  292. }
  293. void draw(NVGcontext *vg);
  294. void onDragStart();
  295. void onDragMove(Vec mouseRel);
  296. void onDragEnd();
  297. };
  298. /** Parent must be a ScrollWidget */
  299. struct ScrollBar : OpaqueWidget {
  300. enum { VERTICAL, HORIZONTAL } orientation;
  301. BNDwidgetState state = BND_DEFAULT;
  302. ScrollBar() {
  303. box.size = Vec(BND_SCROLLBAR_WIDTH, BND_SCROLLBAR_HEIGHT);
  304. }
  305. void draw(NVGcontext *vg);
  306. void onDragStart();
  307. void onDragMove(Vec mouseRel);
  308. void onDragEnd();
  309. };
  310. /** Handles a container with ScrollBar */
  311. struct ScrollWidget : OpaqueWidget {
  312. Widget *container;
  313. ScrollBar *horizontalScrollBar;
  314. ScrollBar *verticalScrollBar;
  315. Vec offset;
  316. ScrollWidget();
  317. void step();
  318. bool onScrollOpaque(Vec scrollRel);
  319. };
  320. struct ZoomWidget : Widget {
  321. float zoom = 1.0;
  322. void draw(NVGcontext *vg);
  323. Widget *onMouseDown(Vec pos, int button);
  324. Widget *onMouseUp(Vec pos, int button);
  325. Widget *onMouseMove(Vec pos, Vec mouseRel);
  326. Widget *onHoverKey(Vec pos, int key);
  327. Widget *onScroll(Vec pos, Vec scrollRel);
  328. };
  329. struct TextField : OpaqueWidget {
  330. std::string text;
  331. std::string placeholder;
  332. int begin = 0;
  333. int end = 0;
  334. TextField() {
  335. box.size.y = BND_WIDGET_HEIGHT;
  336. }
  337. void draw(NVGcontext *vg);
  338. Widget *onMouseDown(Vec pos, int button);
  339. bool onFocusText(int codepoint);
  340. bool onFocusKey(int scancode);
  341. void onFocus();
  342. void insertText(std::string newText);
  343. };
  344. struct PasswordField : TextField {
  345. void draw(NVGcontext *vg);
  346. };
  347. struct ProgressBar : TransparentWidget, QuantityWidget {
  348. ProgressBar() {
  349. box.size.y = BND_WIDGET_HEIGHT;
  350. }
  351. void draw(NVGcontext *vg);
  352. };
  353. struct Tooltip : Widget {
  354. void step();
  355. void draw(NVGcontext *vg);
  356. };
  357. struct Scene : OpaqueWidget {
  358. Widget *overlay = NULL;
  359. void setOverlay(Widget *w);
  360. Menu *createMenu();
  361. void step();
  362. };
  363. ////////////////////
  364. // globals
  365. ////////////////////
  366. extern Vec gMousePos;
  367. extern Widget *gHoveredWidget;
  368. extern Widget *gDraggedWidget;
  369. extern Widget *gDragHoveredWidget;
  370. extern Widget *gFocusedWidget;
  371. extern int gGuiFrame;
  372. extern Scene *gScene;
  373. } // namespace rack