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.

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