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.

465 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. void draw(NVGcontext *vg) override;
  200. };
  201. /** Caches a widget's draw() result to a framebuffer so it is called less frequently
  202. When `dirty` is true, its children will be re-rendered on the next call to step() override.
  203. Events are not passed to the underlying scene.
  204. */
  205. struct FramebufferWidget : virtual Widget {
  206. /** Set this to true to re-render the children to the framebuffer the next time it is drawn */
  207. bool dirty = true;
  208. /** A margin in pixels around the children in the framebuffer
  209. This prevents cutting the rendered SVG off on the box edges.
  210. */
  211. float oversample;
  212. /** The root object in the framebuffer scene
  213. The FramebufferWidget owns the pointer
  214. */
  215. struct Internal;
  216. Internal *internal;
  217. FramebufferWidget();
  218. ~FramebufferWidget();
  219. void draw(NVGcontext *vg) override;
  220. int getImageHandle();
  221. void onZoom() override;
  222. };
  223. struct QuantityWidget : virtual Widget {
  224. float value = 0.0;
  225. float minValue = 0.0;
  226. float maxValue = 1.0;
  227. float defaultValue = 0.0;
  228. std::string label;
  229. /** Include a space character if you want a space after the number, e.g. " Hz" */
  230. std::string unit;
  231. /** The decimal place to round for displaying values.
  232. A precision of 2 will display as "1.00" for example.
  233. */
  234. int precision = 2;
  235. QuantityWidget();
  236. void setValue(float value);
  237. void setLimits(float minValue, float maxValue);
  238. void setDefaultValue(float defaultValue);
  239. /** Generates the display value */
  240. std::string getText();
  241. };
  242. ////////////////////
  243. // GUI widgets
  244. ////////////////////
  245. struct Label : Widget {
  246. std::string text;
  247. Label() {
  248. box.size.y = BND_WIDGET_HEIGHT;
  249. }
  250. void draw(NVGcontext *vg) override;
  251. };
  252. // Deletes itself from parent when clicked
  253. struct MenuOverlay : OpaqueWidget {
  254. void onDragDrop(Widget *origin) override;
  255. bool onScrollOpaque(Vec scrollRel) override {return true;}
  256. Widget *onHoverKey(Vec pos, int key) override;
  257. };
  258. struct MenuEntry;
  259. struct Menu : OpaqueWidget {
  260. Menu *parentMenu = NULL;
  261. Menu *childMenu = NULL;
  262. /** The entry which created the child menu */
  263. MenuEntry *activeEntry = NULL;
  264. Menu() {
  265. box.size = Vec(0, 0);
  266. }
  267. ~Menu();
  268. // Resizes menu and calls addChild()
  269. void pushChild(Widget *child);
  270. void setChildMenu(Menu *menu);
  271. void step() override;
  272. void draw(NVGcontext *vg) override;
  273. bool onScrollOpaque(Vec scrollRel) override;
  274. };
  275. struct MenuEntry : OpaqueWidget {
  276. std::string text;
  277. std::string rightText;
  278. MenuEntry() {
  279. box.size = Vec(0, BND_WIDGET_HEIGHT);
  280. }
  281. void step() override;
  282. };
  283. struct MenuLabel : MenuEntry {
  284. void draw(NVGcontext *vg) override;
  285. };
  286. struct MenuItem : MenuEntry {
  287. void draw(NVGcontext *vg) override;
  288. virtual Menu *createChildMenu() {return NULL;}
  289. void onMouseEnter() override;
  290. void onDragDrop(Widget *origin) override;
  291. };
  292. struct Button : OpaqueWidget {
  293. std::string text;
  294. BNDwidgetState state = BND_DEFAULT;
  295. Button() {
  296. box.size.y = BND_WIDGET_HEIGHT;
  297. }
  298. void draw(NVGcontext *vg) override;
  299. void onMouseEnter() override;
  300. void onMouseLeave() override;
  301. void onDragStart() override;
  302. void onDragEnd() override;
  303. void onDragDrop(Widget *origin) override;
  304. };
  305. struct ChoiceButton : Button {
  306. void draw(NVGcontext *vg) override;
  307. };
  308. struct RadioButton : OpaqueWidget, QuantityWidget {
  309. BNDwidgetState state = BND_DEFAULT;
  310. RadioButton() {
  311. box.size.y = BND_WIDGET_HEIGHT;
  312. }
  313. void draw(NVGcontext *vg) override;
  314. void onMouseEnter() override;
  315. void onMouseLeave() override;
  316. void onDragDrop(Widget *origin) override;
  317. };
  318. struct Slider : OpaqueWidget, QuantityWidget {
  319. BNDwidgetState state = BND_DEFAULT;
  320. Slider() {
  321. box.size.y = BND_WIDGET_HEIGHT;
  322. }
  323. void draw(NVGcontext *vg) override;
  324. void onDragStart() override;
  325. void onDragMove(Vec mouseRel) override;
  326. void onDragEnd() override;
  327. void onMouseDownOpaque(int button) override;
  328. };
  329. /** Parent must be a ScrollWidget */
  330. struct ScrollBar : OpaqueWidget {
  331. enum { VERTICAL, HORIZONTAL } orientation;
  332. BNDwidgetState state = BND_DEFAULT;
  333. ScrollBar() {
  334. box.size = Vec(BND_SCROLLBAR_WIDTH, BND_SCROLLBAR_HEIGHT);
  335. }
  336. void draw(NVGcontext *vg) override;
  337. void onDragStart() override;
  338. void onDragMove(Vec mouseRel) override;
  339. void onDragEnd() override;
  340. };
  341. /** Handles a container with ScrollBar */
  342. struct ScrollWidget : OpaqueWidget {
  343. Widget *container;
  344. ScrollBar *horizontalScrollBar;
  345. ScrollBar *verticalScrollBar;
  346. Vec offset;
  347. ScrollWidget();
  348. void step() override;
  349. bool onScrollOpaque(Vec scrollRel) override;
  350. };
  351. struct TextField : OpaqueWidget {
  352. std::string text;
  353. std::string placeholder;
  354. bool multiline = false;
  355. int begin = 0;
  356. int end = 0;
  357. TextField() {
  358. box.size.y = BND_WIDGET_HEIGHT;
  359. }
  360. void draw(NVGcontext *vg) override;
  361. Widget *onMouseDown(Vec pos, int button) override;
  362. bool onFocusText(int codepoint) override;
  363. bool onFocusKey(int key) override;
  364. bool onFocus() override;
  365. void insertText(std::string newText);
  366. virtual void onTextChange() {}
  367. };
  368. struct PasswordField : TextField {
  369. void draw(NVGcontext *vg) override;
  370. };
  371. struct ProgressBar : TransparentWidget, QuantityWidget {
  372. ProgressBar() {
  373. box.size.y = BND_WIDGET_HEIGHT;
  374. }
  375. void draw(NVGcontext *vg) override;
  376. };
  377. struct Tooltip : Widget {
  378. void step() override;
  379. void draw(NVGcontext *vg) override;
  380. };
  381. struct Scene : OpaqueWidget {
  382. Widget *overlay = NULL;
  383. void setOverlay(Widget *w);
  384. Menu *createMenu();
  385. void step() override;
  386. };
  387. ////////////////////
  388. // globals
  389. ////////////////////
  390. extern Widget *gHoveredWidget;
  391. extern Widget *gDraggedWidget;
  392. extern Widget *gDragHoveredWidget;
  393. extern Widget *gFocusedWidget;
  394. extern Scene *gScene;
  395. } // namespace rack