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.

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