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.

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