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.

477 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 bool onPathDrop(Vec pos, const std::list<std::string>& paths);
  124. virtual void onAction() {}
  125. virtual void onChange() {}
  126. virtual void onZoom();
  127. };
  128. struct TransformWidget : Widget {
  129. /** The transformation matrix */
  130. float transform[6];
  131. TransformWidget();
  132. void identity();
  133. void translate(Vec delta);
  134. void rotate(float angle);
  135. void scale(Vec s);
  136. void draw(NVGcontext *vg) override;
  137. };
  138. struct ZoomWidget : Widget {
  139. float zoom = 1.0;
  140. Vec getRelativeOffset(Vec v, Widget *relative) override;
  141. Rect getViewport(Rect r) override;
  142. void setZoom(float zoom);
  143. void draw(NVGcontext *vg) override;
  144. Widget *onMouseDown(Vec pos, int button) override;
  145. Widget *onMouseUp(Vec pos, int button) override;
  146. Widget *onMouseMove(Vec pos, Vec mouseRel) override;
  147. Widget *onHoverKey(Vec pos, int key) override;
  148. Widget *onScroll(Vec pos, Vec scrollRel) override;
  149. };
  150. ////////////////////
  151. // Trait widgets
  152. ////////////////////
  153. /** Widget that does not respond to events */
  154. struct TransparentWidget : virtual Widget {
  155. Widget *onMouseDown(Vec pos, int button) override {return NULL;}
  156. Widget *onMouseUp(Vec pos, int button) override {return NULL;}
  157. Widget *onMouseMove(Vec pos, Vec mouseRel) override {return NULL;}
  158. Widget *onScroll(Vec pos, Vec scrollRel) override {return NULL;}
  159. };
  160. /** Widget that automatically responds to all mouse events but gives a chance for children to respond instead */
  161. struct OpaqueWidget : virtual Widget {
  162. Widget *onMouseDown(Vec pos, int button) override {
  163. Widget *w = Widget::onMouseDown(pos, button);
  164. if (w) return w;
  165. onMouseDownOpaque(button);
  166. return this;
  167. }
  168. Widget *onMouseUp(Vec pos, int button) override {
  169. Widget *w = Widget::onMouseUp(pos, button);
  170. if (w) return w;
  171. onMouseUpOpaque(button);
  172. return this;
  173. }
  174. Widget *onMouseMove(Vec pos, Vec mouseRel) override {
  175. Widget *w = Widget::onMouseMove(pos, mouseRel);
  176. if (w) return w;
  177. onMouseMoveOpaque(mouseRel);
  178. return this;
  179. }
  180. Widget *onScroll(Vec pos, Vec scrollRel) override {
  181. Widget *w = Widget::onScroll(pos, scrollRel);
  182. if (w) return w;
  183. if (onScrollOpaque(scrollRel))
  184. return this;
  185. return NULL;
  186. }
  187. /** "High level" events called by the above lower level events.
  188. Use these if you don't care about the clicked position.
  189. */
  190. virtual void onMouseDownOpaque(int button) {}
  191. virtual void onMouseUpOpaque(int button) {}
  192. virtual void onMouseMoveOpaque(Vec mouseRel) {}
  193. virtual bool onScrollOpaque(Vec scrollRel) {return false;}
  194. };
  195. struct SpriteWidget : virtual Widget {
  196. Vec spriteOffset;
  197. Vec spriteSize;
  198. std::shared_ptr<Image> spriteImage;
  199. int index = 0;
  200. void draw(NVGcontext *vg) override;
  201. };
  202. struct SVGWidget : virtual Widget {
  203. std::shared_ptr<SVG> svg;
  204. /** Sets the box size to the svg image size */
  205. void wrap();
  206. /** Sets and wraps the SVG */
  207. void setSVG(std::shared_ptr<SVG> svg);
  208. void draw(NVGcontext *vg) override;
  209. };
  210. /** Caches a widget's draw() result to a framebuffer so it is called less frequently
  211. When `dirty` is true, its children will be re-rendered on the next call to step() override.
  212. Events are not passed to the underlying scene.
  213. */
  214. struct FramebufferWidget : virtual Widget {
  215. /** Set this to true to re-render the children to the framebuffer the next time it is drawn */
  216. bool dirty = true;
  217. /** A margin in pixels around the children in the framebuffer
  218. This prevents cutting the rendered SVG off on the box edges.
  219. */
  220. float oversample;
  221. /** The root object in the framebuffer scene
  222. The FramebufferWidget owns the pointer
  223. */
  224. struct Internal;
  225. Internal *internal;
  226. FramebufferWidget();
  227. ~FramebufferWidget();
  228. void draw(NVGcontext *vg) override;
  229. int getImageHandle();
  230. void onZoom() override;
  231. };
  232. struct QuantityWidget : virtual Widget {
  233. float value = 0.0;
  234. float minValue = 0.0;
  235. float maxValue = 1.0;
  236. float defaultValue = 0.0;
  237. std::string label;
  238. /** Include a space character if you want a space after the number, e.g. " Hz" */
  239. std::string unit;
  240. /** The decimal place to round for displaying values.
  241. A precision of 2 will display as "1.00" for example.
  242. */
  243. int precision = 2;
  244. QuantityWidget();
  245. void setValue(float value);
  246. void setLimits(float minValue, float maxValue);
  247. void setDefaultValue(float defaultValue);
  248. /** Generates the display value */
  249. std::string getText();
  250. };
  251. ////////////////////
  252. // GUI widgets
  253. ////////////////////
  254. struct Label : Widget {
  255. std::string text;
  256. Label() {
  257. box.size.y = BND_WIDGET_HEIGHT;
  258. }
  259. void draw(NVGcontext *vg) override;
  260. };
  261. // Deletes itself from parent when clicked
  262. struct MenuOverlay : OpaqueWidget {
  263. void onDragDrop(Widget *origin) override;
  264. bool onScrollOpaque(Vec scrollRel) override {return true;}
  265. Widget *onHoverKey(Vec pos, int key) override;
  266. };
  267. struct MenuEntry;
  268. struct Menu : OpaqueWidget {
  269. Menu *parentMenu = NULL;
  270. Menu *childMenu = NULL;
  271. /** The entry which created the child menu */
  272. MenuEntry *activeEntry = NULL;
  273. Menu() {
  274. box.size = Vec(0, 0);
  275. }
  276. ~Menu();
  277. // Resizes menu and calls addChild()
  278. void pushChild(Widget *child);
  279. void setChildMenu(Menu *menu);
  280. void step() override;
  281. void draw(NVGcontext *vg) override;
  282. bool onScrollOpaque(Vec scrollRel) override;
  283. };
  284. struct MenuEntry : OpaqueWidget {
  285. std::string text;
  286. std::string rightText;
  287. MenuEntry() {
  288. box.size = Vec(0, BND_WIDGET_HEIGHT);
  289. }
  290. void step() override;
  291. };
  292. struct MenuLabel : MenuEntry {
  293. void draw(NVGcontext *vg) override;
  294. };
  295. struct MenuItem : MenuEntry {
  296. void draw(NVGcontext *vg) override;
  297. virtual Menu *createChildMenu() {return NULL;}
  298. void onMouseEnter() override;
  299. void onDragDrop(Widget *origin) override;
  300. };
  301. struct Button : OpaqueWidget {
  302. std::string text;
  303. BNDwidgetState state = BND_DEFAULT;
  304. Button() {
  305. box.size.y = BND_WIDGET_HEIGHT;
  306. }
  307. void draw(NVGcontext *vg) override;
  308. void onMouseEnter() override;
  309. void onMouseLeave() override;
  310. void onDragStart() override;
  311. void onDragEnd() override;
  312. void onDragDrop(Widget *origin) override;
  313. };
  314. struct ChoiceButton : Button {
  315. void draw(NVGcontext *vg) override;
  316. };
  317. struct RadioButton : OpaqueWidget, QuantityWidget {
  318. BNDwidgetState state = BND_DEFAULT;
  319. RadioButton() {
  320. box.size.y = BND_WIDGET_HEIGHT;
  321. }
  322. void draw(NVGcontext *vg) override;
  323. void onMouseEnter() override;
  324. void onMouseLeave() override;
  325. void onDragDrop(Widget *origin) override;
  326. };
  327. struct Slider : OpaqueWidget, QuantityWidget {
  328. BNDwidgetState state = BND_DEFAULT;
  329. Slider() {
  330. box.size.y = BND_WIDGET_HEIGHT;
  331. }
  332. void draw(NVGcontext *vg) override;
  333. void onDragStart() override;
  334. void onDragMove(Vec mouseRel) override;
  335. void onDragEnd() override;
  336. void onMouseDownOpaque(int button) override;
  337. };
  338. /** Parent must be a ScrollWidget */
  339. struct ScrollBar : OpaqueWidget {
  340. enum { VERTICAL, HORIZONTAL } orientation;
  341. BNDwidgetState state = BND_DEFAULT;
  342. ScrollBar() {
  343. box.size = Vec(BND_SCROLLBAR_WIDTH, BND_SCROLLBAR_HEIGHT);
  344. }
  345. void draw(NVGcontext *vg) override;
  346. void onDragStart() override;
  347. void onDragMove(Vec mouseRel) override;
  348. void onDragEnd() override;
  349. };
  350. /** Handles a container with ScrollBar */
  351. struct ScrollWidget : OpaqueWidget {
  352. Widget *container;
  353. ScrollBar *horizontalScrollBar;
  354. ScrollBar *verticalScrollBar;
  355. Vec offset;
  356. ScrollWidget();
  357. void step() override;
  358. bool onScrollOpaque(Vec scrollRel) override;
  359. };
  360. struct TextField : OpaqueWidget {
  361. std::string text;
  362. std::string placeholder;
  363. bool multiline = false;
  364. int begin = 0;
  365. int end = 0;
  366. TextField() {
  367. box.size.y = BND_WIDGET_HEIGHT;
  368. }
  369. void draw(NVGcontext *vg) override;
  370. Widget *onMouseDown(Vec pos, int button) override;
  371. bool onFocusText(int codepoint) override;
  372. bool onFocusKey(int key) override;
  373. bool onFocus() override;
  374. void insertText(std::string newText);
  375. virtual void onTextChange() {}
  376. };
  377. struct PasswordField : TextField {
  378. void draw(NVGcontext *vg) override;
  379. };
  380. struct ProgressBar : TransparentWidget, QuantityWidget {
  381. ProgressBar() {
  382. box.size.y = BND_WIDGET_HEIGHT;
  383. }
  384. void draw(NVGcontext *vg) override;
  385. };
  386. struct Tooltip : Widget {
  387. void step() override;
  388. void draw(NVGcontext *vg) override;
  389. };
  390. struct Scene : OpaqueWidget {
  391. Widget *overlay = NULL;
  392. void setOverlay(Widget *w);
  393. Menu *createMenu();
  394. void step() override;
  395. };
  396. ////////////////////
  397. // globals
  398. ////////////////////
  399. extern Widget *gHoveredWidget;
  400. extern Widget *gDraggedWidget;
  401. extern Widget *gDragHoveredWidget;
  402. extern Widget *gFocusedWidget;
  403. extern Scene *gScene;
  404. } // namespace rack