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.

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