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 9.4KB

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
123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310
  1. #pragma once
  2. #include <list>
  3. #include <memory>
  4. #include "nanovg.h"
  5. #include "nanosvg.h"
  6. #include "util/common.hpp"
  7. #include "events.hpp"
  8. #include "util/color.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 window.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. Never inherit from Widget directly. Instead, inherit from VirtualWidget declared below.
  38. */
  39. struct Widget {
  40. /** Stores position and size */
  41. Rect box = Rect(Vec(), Vec(INFINITY, INFINITY));
  42. Widget *parent = NULL;
  43. std::list<Widget*> children;
  44. bool visible = true;
  45. virtual ~Widget();
  46. virtual Rect getChildrenBoundingBox();
  47. /** Returns `v` transformed into the coordinate system of `relative` */
  48. virtual Vec getRelativeOffset(Vec v, Widget *relative);
  49. /** Returns `v` transformed into world coordinates */
  50. Vec getAbsoluteOffset(Vec v) {
  51. return getRelativeOffset(v, NULL);
  52. }
  53. /** Returns a subset of the given Rect bounded by the box of this widget and all ancestors */
  54. virtual Rect getViewport(Rect r);
  55. template <class T>
  56. T *getAncestorOfType() {
  57. if (!parent) return NULL;
  58. T *p = dynamic_cast<T*>(parent);
  59. if (p) return p;
  60. return parent->getAncestorOfType<T>();
  61. }
  62. template <class T>
  63. T *getFirstDescendantOfType() {
  64. for (Widget *child : children) {
  65. T *c = dynamic_cast<T*>(child);
  66. if (c) return c;
  67. c = child->getFirstDescendantOfType<T>();
  68. if (c) return c;
  69. }
  70. return NULL;
  71. }
  72. /** Adds widget to list of children.
  73. Gives ownership of widget to this widget instance.
  74. */
  75. void addChild(Widget *widget);
  76. /** Removes widget from list of children if it exists.
  77. Does not delete widget but transfers ownership to caller
  78. */
  79. void removeChild(Widget *widget);
  80. /** Removes and deletes all children */
  81. void clearChildren();
  82. /** Recursively finalizes event start/end pairs as needed */
  83. void finalizeEvents();
  84. /** Advances the module by one frame */
  85. virtual void step();
  86. /** Draws to NanoVG context */
  87. virtual void draw(NVGcontext *vg);
  88. // Events
  89. /** Called when a mouse button is pressed over this widget */
  90. virtual void onMouseDown(EventMouseDown &e);
  91. /** Called when a mouse button is released over this widget */
  92. virtual void onMouseUp(EventMouseUp &e);
  93. /** Called when the mouse moves over this widget.
  94. Called on every frame, even if `mouseRel = Vec(0, 0)`.
  95. */
  96. virtual void onMouseMove(EventMouseMove &e);
  97. /** Called when a key is pressed while hovering over this widget */
  98. virtual void onHoverKey(EventHoverKey &e);
  99. /** Called when this widget begins responding to `onMouseMove` events */
  100. virtual void onMouseEnter(EventMouseEnter &e) {}
  101. /** Called when this widget no longer responds to `onMouseMove` events */
  102. virtual void onMouseLeave(EventMouseLeave &e) {}
  103. /** Called when this widget gains focus by responding to the `onMouseDown` event */
  104. virtual void onFocus(EventFocus &e) {}
  105. virtual void onDefocus(EventDefocus &e) {}
  106. /** Called when a printable character is received while this widget is focused */
  107. virtual void onText(EventText &e) {}
  108. /** Called when a key is pressed while this widget is focused */
  109. virtual void onKey(EventKey &e) {}
  110. /** Called when the scroll wheel is moved while the mouse is hovering over this widget */
  111. virtual void onScroll(EventScroll &e);
  112. /** Called when a widget responds to `onMouseDown` for a left button press */
  113. virtual void onDragStart(EventDragStart &e) {}
  114. /** Called when the left button is released and this widget is being dragged */
  115. virtual void onDragEnd(EventDragEnd &e) {}
  116. /** Called when a widget responds to `onMouseMove` and is being dragged */
  117. virtual void onDragMove(EventDragMove &e) {}
  118. /** Called when a widget responds to `onMouseUp` for a left button release and a widget is being dragged */
  119. virtual void onDragEnter(EventDragEnter &e) {}
  120. virtual void onDragLeave(EventDragEnter &e) {}
  121. /** Called when a drag action ends while hovering this widget */
  122. virtual void onDragDrop(EventDragDrop &e) {}
  123. /** Called when an OS selection of files is dragged-and-dropped on this widget */
  124. virtual void onPathDrop(EventPathDrop &e);
  125. /** Called when an event triggers an action */
  126. virtual void onAction(EventAction &e) {}
  127. /** For widgets with some concept of values, called when the value is changed */
  128. virtual void onChange(EventChange &e) {}
  129. /** Called when the zoom level is changed of this widget */
  130. virtual void onZoom(EventZoom &e);
  131. /** Helper function for creating and initializing a Widget with certain arguments (in this case just the position).
  132. 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.
  133. Example:
  134. addChild(Widget::create<SVGWidget>(Vec(10, 10)))
  135. */
  136. template <typename T = Widget>
  137. static T *create(Vec pos = Vec()) {
  138. T *o = new T();
  139. o->box.pos = pos;
  140. return o;
  141. }
  142. };
  143. /** Instead of inheriting from Widget directly, inherit from VirtualWidget to guarantee that only one copy of Widget's member variables are used by each instance of the Widget hierarchy.
  144. */
  145. struct VirtualWidget : virtual Widget {};
  146. struct TransformWidget : VirtualWidget {
  147. /** The transformation matrix */
  148. float transform[6];
  149. TransformWidget();
  150. Rect getChildrenBoundingBox() override;
  151. void identity();
  152. void translate(Vec delta);
  153. void rotate(float angle);
  154. void scale(Vec s);
  155. void draw(NVGcontext *vg) override;
  156. };
  157. struct ZoomWidget : VirtualWidget {
  158. float zoom = 1.0;
  159. Vec getRelativeOffset(Vec v, Widget *relative) override;
  160. Rect getViewport(Rect r) override;
  161. void setZoom(float zoom);
  162. void draw(NVGcontext *vg) override;
  163. void onMouseDown(EventMouseDown &e) override;
  164. void onMouseUp(EventMouseUp &e) override;
  165. void onMouseMove(EventMouseMove &e) override;
  166. void onHoverKey(EventHoverKey &e) override;
  167. void onScroll(EventScroll &e) override;
  168. void onPathDrop(EventPathDrop &e) override;
  169. };
  170. ////////////////////
  171. // Trait widgets
  172. ////////////////////
  173. /** Widget that does not respond to events */
  174. struct TransparentWidget : VirtualWidget {
  175. void onMouseDown(EventMouseDown &e) override {}
  176. void onMouseUp(EventMouseUp &e) override {}
  177. void onMouseMove(EventMouseMove &e) override {}
  178. void onScroll(EventScroll &e) override {}
  179. };
  180. /** Widget that automatically responds to all mouse events but gives a chance for children to respond instead */
  181. struct OpaqueWidget : VirtualWidget {
  182. void onMouseDown(EventMouseDown &e) override {
  183. Widget::onMouseDown(e);
  184. if (!e.target)
  185. e.target = this;
  186. e.consumed = true;
  187. }
  188. void onMouseUp(EventMouseUp &e) override {
  189. Widget::onMouseUp(e);
  190. if (!e.target)
  191. e.target = this;
  192. e.consumed = true;
  193. }
  194. void onMouseMove(EventMouseMove &e) override {
  195. Widget::onMouseMove(e);
  196. if (!e.target)
  197. e.target = this;
  198. e.consumed = true;
  199. }
  200. void onScroll(EventScroll &e) override {
  201. Widget::onScroll(e);
  202. e.consumed = true;
  203. }
  204. };
  205. struct SpriteWidget : VirtualWidget {
  206. Vec spriteOffset;
  207. Vec spriteSize;
  208. std::shared_ptr<Image> spriteImage;
  209. int index = 0;
  210. void draw(NVGcontext *vg) override;
  211. };
  212. struct SVGWidget : VirtualWidget {
  213. std::shared_ptr<SVG> svg;
  214. /** Sets the box size to the svg image size */
  215. void wrap();
  216. /** Sets and wraps the SVG */
  217. void setSVG(std::shared_ptr<SVG> svg);
  218. void draw(NVGcontext *vg) override;
  219. };
  220. /** Caches a widget's draw() result to a framebuffer so it is called less frequently
  221. When `dirty` is true, its children will be re-rendered on the next call to step() override.
  222. Events are not passed to the underlying scene.
  223. */
  224. struct FramebufferWidget : VirtualWidget {
  225. /** Set this to true to re-render the children to the framebuffer the next time it is drawn */
  226. bool dirty = true;
  227. /** A margin in pixels around the children in the framebuffer
  228. This prevents cutting the rendered SVG off on the box edges.
  229. */
  230. float oversample;
  231. /** The root object in the framebuffer scene
  232. The FramebufferWidget owns the pointer
  233. */
  234. struct Internal;
  235. Internal *internal;
  236. FramebufferWidget();
  237. ~FramebufferWidget();
  238. void draw(NVGcontext *vg) override;
  239. int getImageHandle();
  240. void onZoom(EventZoom &e) override;
  241. };
  242. /** A Widget representing a float value */
  243. struct QuantityWidget : VirtualWidget {
  244. float value = 0.0;
  245. float minValue = 0.0;
  246. float maxValue = 1.0;
  247. float defaultValue = 0.0;
  248. std::string label;
  249. /** Include a space character if you want a space after the number, e.g. " Hz" */
  250. std::string unit;
  251. /** The decimal place to round for displaying values.
  252. A precision of 2 will display as "1.00" for example.
  253. */
  254. int precision = 2;
  255. QuantityWidget();
  256. void setValue(float value);
  257. void setLimits(float minValue, float maxValue);
  258. void setDefaultValue(float defaultValue);
  259. /** Generates the display value */
  260. std::string getText();
  261. };
  262. ////////////////////
  263. // globals
  264. ////////////////////
  265. extern Widget *gHoveredWidget;
  266. extern Widget *gDraggedWidget;
  267. extern Widget *gDragHoveredWidget;
  268. extern Widget *gFocusedWidget;
  269. extern Widget *gTempWidget;
  270. } // namespace rack