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.

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