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