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.

widgets.hpp 12KB

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