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.

456 lines
12KB

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