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