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.

483 lines
13KB

  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/common.hpp"
  8. #include "events.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. virtual 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 void onMouseDown(EventMouseDown &e);
  93. virtual void onMouseUp(EventMouseUp &e);
  94. /** Called on every frame, even if mouseRel = Vec(0, 0) */
  95. virtual void onMouseMove(EventMouseMove &e);
  96. virtual void onHoverKey(EventHoverKey &e);
  97. /** Called when this widget begins responding to `onMouseMove` events */
  98. virtual void onMouseEnter(EventMouseEnter &e) {}
  99. /** Called when another widget begins responding to `onMouseMove` events */
  100. virtual void onMouseLeave(EventMouseLeave &e) {}
  101. virtual void onFocus(EventFocus &e) {}
  102. virtual void onDefocus(EventDefocus &e) {}
  103. virtual void onText(EventText &e) {}
  104. virtual void onKey(EventKey &e) {}
  105. virtual void onScroll(EventScroll &e);
  106. /** Called when a widget responds to `onMouseDown` for a left button press */
  107. virtual void onDragStart(EventDragStart &e) {}
  108. /** Called when the left button is released and this widget is being dragged */
  109. virtual void onDragEnd(EventDragEnd &e) {}
  110. /** Called when a widget responds to `onMouseMove` and is being dragged */
  111. virtual void onDragMove(EventDragMove &e) {}
  112. /** Called when a widget responds to `onMouseUp` for a left button release and a widget is being dragged */
  113. virtual void onDragEnter(EventDragEnter &e) {}
  114. virtual void onDragLeave(EventDragEnter &e) {}
  115. virtual void onDragDrop(EventDragDrop &e) {}
  116. virtual void onPathDrop(EventPathDrop &e);
  117. virtual void onAction(EventAction &e) {}
  118. virtual void onChange(EventChange &e) {}
  119. virtual void onZoom(EventZoom &e);
  120. /** Helper function for creating and initializing a Widget with certain arguments (in this case just the position).
  121. In this project, you will find this idiom everywhere, as an easier alternative to constructor arguments, for building a Widget (or a subclass) with a one-liner.
  122. Example:
  123. addChild(Widget::create<SVGWidget>(Vec(0, 0)))
  124. */
  125. template <typename T = Widget>
  126. static T *create(Vec pos) {
  127. T *o = new T();
  128. o->box.pos = pos;
  129. return o;
  130. }
  131. };
  132. struct TransformWidget : Widget {
  133. /** The transformation matrix */
  134. float transform[6];
  135. TransformWidget();
  136. Rect getChildrenBoundingBox() override;
  137. void identity();
  138. void translate(Vec delta);
  139. void rotate(float angle);
  140. void scale(Vec s);
  141. void draw(NVGcontext *vg) override;
  142. };
  143. struct ZoomWidget : Widget {
  144. float zoom = 1.0;
  145. Vec getRelativeOffset(Vec v, Widget *relative) override;
  146. Rect getViewport(Rect r) override;
  147. void setZoom(float zoom);
  148. void draw(NVGcontext *vg) override;
  149. void onMouseDown(EventMouseDown &e) override;
  150. void onMouseUp(EventMouseUp &e) override;
  151. void onMouseMove(EventMouseMove &e) override;
  152. void onHoverKey(EventHoverKey &e) override;
  153. void onScroll(EventScroll &e) override;
  154. void onPathDrop(EventPathDrop &e) override;
  155. };
  156. ////////////////////
  157. // Trait widgets
  158. ////////////////////
  159. /** Widget that does not respond to events */
  160. struct TransparentWidget : virtual Widget {
  161. void onMouseDown(EventMouseDown &e) override {}
  162. void onMouseUp(EventMouseUp &e) override {}
  163. void onMouseMove(EventMouseMove &e) override {}
  164. void onScroll(EventScroll &e) override {}
  165. };
  166. /** Widget that automatically responds to all mouse events but gives a chance for children to respond instead */
  167. struct OpaqueWidget : virtual Widget {
  168. void onMouseDown(EventMouseDown &e) override {
  169. Widget::onMouseDown(e);
  170. if (!e.target)
  171. e.target = this;
  172. e.consumed = true;
  173. }
  174. void onMouseUp(EventMouseUp &e) override {
  175. Widget::onMouseUp(e);
  176. if (!e.target)
  177. e.target = this;
  178. e.consumed = true;
  179. }
  180. void onMouseMove(EventMouseMove &e) override {
  181. Widget::onMouseMove(e);
  182. if (!e.target)
  183. e.target = this;
  184. e.consumed = true;
  185. }
  186. void onScroll(EventScroll &e) override {
  187. Widget::onScroll(e);
  188. e.consumed = true;
  189. }
  190. };
  191. struct SpriteWidget : virtual Widget {
  192. Vec spriteOffset;
  193. Vec spriteSize;
  194. std::shared_ptr<Image> spriteImage;
  195. int index = 0;
  196. void draw(NVGcontext *vg) override;
  197. };
  198. struct SVGWidget : virtual Widget {
  199. std::shared_ptr<SVG> svg;
  200. /** Sets the box size to the svg image size */
  201. void wrap();
  202. /** Sets and wraps the SVG */
  203. void setSVG(std::shared_ptr<SVG> svg);
  204. void draw(NVGcontext *vg) override;
  205. };
  206. /** Caches a widget's draw() result to a framebuffer so it is called less frequently
  207. When `dirty` is true, its children will be re-rendered on the next call to step() override.
  208. Events are not passed to the underlying scene.
  209. */
  210. struct FramebufferWidget : virtual Widget {
  211. /** Set this to true to re-render the children to the framebuffer the next time it is drawn */
  212. bool dirty = true;
  213. /** A margin in pixels around the children in the framebuffer
  214. This prevents cutting the rendered SVG off on the box edges.
  215. */
  216. float oversample;
  217. /** The root object in the framebuffer scene
  218. The FramebufferWidget owns the pointer
  219. */
  220. struct Internal;
  221. Internal *internal;
  222. FramebufferWidget();
  223. ~FramebufferWidget();
  224. void draw(NVGcontext *vg) override;
  225. int getImageHandle();
  226. void onZoom(EventZoom &e) override;
  227. };
  228. struct QuantityWidget : virtual Widget {
  229. float value = 0.0;
  230. float minValue = 0.0;
  231. float maxValue = 1.0;
  232. float defaultValue = 0.0;
  233. std::string label;
  234. /** Include a space character if you want a space after the number, e.g. " Hz" */
  235. std::string unit;
  236. /** The decimal place to round for displaying values.
  237. A precision of 2 will display as "1.00" for example.
  238. */
  239. int precision = 2;
  240. QuantityWidget();
  241. void setValue(float value);
  242. void setLimits(float minValue, float maxValue);
  243. void setDefaultValue(float defaultValue);
  244. /** Generates the display value */
  245. std::string getText();
  246. };
  247. ////////////////////
  248. // GUI widgets
  249. ////////////////////
  250. struct Label : Widget {
  251. std::string text;
  252. Label() {
  253. box.size.y = BND_WIDGET_HEIGHT;
  254. }
  255. void draw(NVGcontext *vg) override;
  256. };
  257. /** Deletes itself from parent when clicked */
  258. struct MenuOverlay : OpaqueWidget {
  259. void step() override;
  260. void onMouseDown(EventMouseDown &e) override;
  261. void onHoverKey(EventHoverKey &e) override;
  262. };
  263. struct MenuEntry;
  264. struct Menu : OpaqueWidget {
  265. Menu *parentMenu = NULL;
  266. Menu *childMenu = NULL;
  267. /** The entry which created the child menu */
  268. MenuEntry *activeEntry = NULL;
  269. Menu() {
  270. box.size = Vec(0, 0);
  271. }
  272. ~Menu();
  273. // Resizes menu and calls addChild()
  274. void pushChild(Widget *child) DEPRECATED {
  275. addChild(child);
  276. }
  277. void setChildMenu(Menu *menu);
  278. void step() override;
  279. void draw(NVGcontext *vg) override;
  280. void onScroll(EventScroll &e) override;
  281. };
  282. struct MenuEntry : OpaqueWidget {
  283. std::string text;
  284. MenuEntry() {
  285. box.size = Vec(0, BND_WIDGET_HEIGHT);
  286. }
  287. };
  288. struct MenuLabel : MenuEntry {
  289. void draw(NVGcontext *vg) override;
  290. void step() override;
  291. };
  292. struct MenuItem : MenuEntry {
  293. std::string rightText;
  294. void draw(NVGcontext *vg) override;
  295. void step() override;
  296. virtual Menu *createChildMenu() {return NULL;}
  297. void onMouseEnter(EventMouseEnter &e) override;
  298. void onDragDrop(EventDragDrop &e) override;
  299. };
  300. struct WindowOverlay : OpaqueWidget {
  301. };
  302. struct Window : OpaqueWidget {
  303. std::string title;
  304. void draw(NVGcontext *vg) override;
  305. void onDragMove(EventDragMove &e) override;
  306. };
  307. struct Button : OpaqueWidget {
  308. std::string text;
  309. BNDwidgetState state = BND_DEFAULT;
  310. Button() {
  311. box.size.y = BND_WIDGET_HEIGHT;
  312. }
  313. void draw(NVGcontext *vg) override;
  314. void onMouseEnter(EventMouseEnter &e) override;
  315. void onMouseLeave(EventMouseLeave &e) override;
  316. void onDragStart(EventDragStart &e) override;
  317. void onDragEnd(EventDragEnd &e) override;
  318. void onDragDrop(EventDragDrop &e) override;
  319. };
  320. struct ChoiceButton : Button {
  321. void draw(NVGcontext *vg) override;
  322. };
  323. struct RadioButton : OpaqueWidget, QuantityWidget {
  324. BNDwidgetState state = BND_DEFAULT;
  325. RadioButton() {
  326. box.size.y = BND_WIDGET_HEIGHT;
  327. }
  328. void draw(NVGcontext *vg) override;
  329. void onMouseEnter(EventMouseEnter &e) override;
  330. void onMouseLeave(EventMouseLeave &e) override;
  331. void onDragDrop(EventDragDrop &e) override;
  332. };
  333. struct Slider : OpaqueWidget, QuantityWidget {
  334. BNDwidgetState state = BND_DEFAULT;
  335. Slider() {
  336. box.size.y = BND_WIDGET_HEIGHT;
  337. }
  338. void draw(NVGcontext *vg) override;
  339. void onDragStart(EventDragStart &e) override;
  340. void onDragMove(EventDragMove &e) override;
  341. void onDragEnd(EventDragEnd &e) override;
  342. void onMouseDown(EventMouseDown &e) override;
  343. };
  344. /** Parent must be a ScrollWidget */
  345. struct ScrollBar : OpaqueWidget {
  346. enum { VERTICAL, HORIZONTAL } orientation;
  347. BNDwidgetState state = BND_DEFAULT;
  348. float offset = 0.0;
  349. float size = 0.0;
  350. ScrollBar() {
  351. box.size = Vec(BND_SCROLLBAR_WIDTH, BND_SCROLLBAR_HEIGHT);
  352. }
  353. void draw(NVGcontext *vg) override;
  354. void onDragStart(EventDragStart &e) override;
  355. void onDragMove(EventDragMove &e) override;
  356. void onDragEnd(EventDragEnd &e) override;
  357. };
  358. /** Handles a container with ScrollBar */
  359. struct ScrollWidget : OpaqueWidget {
  360. Widget *container;
  361. ScrollBar *horizontalScrollBar;
  362. ScrollBar *verticalScrollBar;
  363. Vec offset;
  364. ScrollWidget();
  365. void draw(NVGcontext *vg) override;
  366. void step() override;
  367. void onMouseMove(EventMouseMove &e) override;
  368. void onScroll(EventScroll &e) override;
  369. };
  370. struct TextField : OpaqueWidget {
  371. std::string text;
  372. std::string placeholder;
  373. bool multiline = false;
  374. int begin = 0;
  375. int end = 0;
  376. TextField() {
  377. box.size.y = BND_WIDGET_HEIGHT;
  378. }
  379. void draw(NVGcontext *vg) override;
  380. void onMouseDown(EventMouseDown &e) override;
  381. void onFocus(EventFocus &e) override;
  382. void onText(EventText &e) override;
  383. void onKey(EventKey &e) override;
  384. void insertText(std::string newText);
  385. virtual void onTextChange() {}
  386. };
  387. struct PasswordField : TextField {
  388. void draw(NVGcontext *vg) override;
  389. };
  390. struct ProgressBar : TransparentWidget, QuantityWidget {
  391. ProgressBar() {
  392. box.size.y = BND_WIDGET_HEIGHT;
  393. }
  394. void draw(NVGcontext *vg) override;
  395. };
  396. struct Tooltip : Widget {
  397. void step() override;
  398. void draw(NVGcontext *vg) override;
  399. };
  400. struct Scene : OpaqueWidget {
  401. Widget *overlay = NULL;
  402. void setOverlay(Widget *w);
  403. Menu *createMenu();
  404. void step() override;
  405. };
  406. ////////////////////
  407. // globals
  408. ////////////////////
  409. extern Widget *gHoveredWidget;
  410. extern Widget *gDraggedWidget;
  411. extern Widget *gDragHoveredWidget;
  412. extern Widget *gFocusedWidget;
  413. extern Scene *gScene;
  414. } // namespace rack