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.

420 lines
10KB

  1. #pragma once
  2. #include <common.hpp>
  3. #include <math.hpp>
  4. #include <vector>
  5. #include <set>
  6. /** Remaps Ctrl to Cmd on Mac
  7. Use this instead of GLFW_MOD_CONTROL, since Cmd should be used on Mac in place of Ctrl on Linux/Windows.
  8. */
  9. #if defined ARCH_MAC
  10. #define RACK_MOD_CTRL GLFW_MOD_SUPER
  11. #define RACK_MOD_CTRL_NAME "Cmd"
  12. #else
  13. #define RACK_MOD_CTRL GLFW_MOD_CONTROL
  14. #define RACK_MOD_CTRL_NAME "Ctrl"
  15. #endif
  16. #define RACK_MOD_SHIFT_NAME "Shift"
  17. #define RACK_MOD_ALT_NAME "Alt"
  18. /** Filters actual mod keys from the mod flags.
  19. Use this if you don't care about GLFW_MOD_CAPS_LOCK and GLFW_MOD_NUM_LOCK.
  20. Example usage:
  21. if ((e.mod & RACK_MOD_MASK) == (RACK_MOD_CTRL | GLFW_MOD_SHIFT)) ...
  22. */
  23. #define RACK_MOD_MASK (GLFW_MOD_SHIFT | GLFW_MOD_CONTROL | GLFW_MOD_ALT | GLFW_MOD_SUPER)
  24. namespace rack {
  25. namespace widget {
  26. struct Widget;
  27. }
  28. /** Handles user interaction with Widget.
  29. */
  30. namespace event {
  31. /** A per-event state shared and writable by all widgets that recursively handle an event. */
  32. struct Context {
  33. /** Whether the event should continue recursing to children Widgets. */
  34. bool propagating = true;
  35. /** Whether the event has been consumed by an event handler and no more handlers should consume the event. */
  36. bool consumed = false;
  37. /** The widget that responded to the event. */
  38. widget::Widget* target = NULL;
  39. };
  40. /** Base class for all events. */
  41. struct Base {
  42. Context* context = NULL;
  43. /** Prevents the event from being handled by more Widgets.
  44. */
  45. void stopPropagating() const {
  46. if (!context)
  47. return;
  48. context->propagating = false;
  49. }
  50. bool isPropagating() const {
  51. if (!context)
  52. return true;
  53. return context->propagating;
  54. }
  55. /** Tells the event handler that a particular Widget consumed the event.
  56. You usually want to stop propagation as well, so call consume() instead.
  57. */
  58. void setTarget(widget::Widget* w) const {
  59. if (!context)
  60. return;
  61. context->target = w;
  62. }
  63. widget::Widget* getTarget() const {
  64. if (!context)
  65. return NULL;
  66. return context->target;
  67. }
  68. /** Sets the target Widget and stops propagating.
  69. A NULL Widget may be passed to consume but not set a target.
  70. */
  71. void consume(widget::Widget* w) const {
  72. if (!context)
  73. return;
  74. context->propagating = false;
  75. context->consumed = true;
  76. context->target = w;
  77. }
  78. bool isConsumed() const {
  79. if (!context)
  80. return false;
  81. return context->consumed;
  82. }
  83. };
  84. /** An event prototype with a vector position. */
  85. struct PositionBase {
  86. /** The pixel coordinate where the event occurred, relative to the Widget it is called on. */
  87. math::Vec pos;
  88. };
  89. #define RACK_HELD 3
  90. /** An event prototype with a GLFW key. */
  91. struct KeyBase {
  92. /** GLFW_KEY_* */
  93. int key;
  94. /** GLFW_KEY_*. You should usually use `key` instead. */
  95. int scancode;
  96. /** GLFW_RELEASE, GLFW_PRESS, GLFW_REPEAT, or RACK_HELD */
  97. int action;
  98. /** GLFW_MOD_* */
  99. int mods;
  100. };
  101. /** An event prototype with a Unicode character. */
  102. struct TextBase {
  103. /** Unicode code point of the character */
  104. int codepoint;
  105. };
  106. /** Occurs every frame when the mouse is hovering over a Widget.
  107. Recurses.
  108. Consume this event to allow Enter and Leave to occur.
  109. */
  110. struct Hover : Base, PositionBase {
  111. /** Change in mouse position since the last frame. Can be zero. */
  112. math::Vec mouseDelta;
  113. };
  114. /** Occurs each mouse button press or release.
  115. Recurses.
  116. Consume this event to allow DoubleClick, Select, Deselect, SelectKey, SelectText, DragStart, DragEnd, DragMove, and DragDrop to occur.
  117. */
  118. struct Button : Base, PositionBase {
  119. /** GLFW_MOUSE_BUTTON_LEFT, GLFW_MOUSE_BUTTON_RIGHT, GLFW_MOUSE_BUTTON_MIDDLE, etc. */
  120. int button;
  121. /** GLFW_PRESS or GLFW_RELEASE */
  122. int action;
  123. /** GLFW_MOD_* */
  124. int mods;
  125. };
  126. /** Occurs when the left mouse button is pressed a second time on the same Widget within a time duration.
  127. Must consume the Button event (on left button press) to receive this event.
  128. */
  129. struct DoubleClick : Base {
  130. };
  131. /** Occurs when a key is pressed, released, or repeated while the mouse is hovering a Widget.
  132. Recurses.
  133. */
  134. struct HoverKey : Base, PositionBase, KeyBase {
  135. };
  136. /** Occurs when a character is typed while the mouse is hovering a Widget.
  137. Recurses.
  138. */
  139. struct HoverText : Base, PositionBase, TextBase {
  140. };
  141. /** Occurs when the mouse scroll wheel is moved while the mouse is hovering a Widget.
  142. Recurses.
  143. */
  144. struct HoverScroll : Base, PositionBase {
  145. /** Change of scroll wheel position. */
  146. math::Vec scrollDelta;
  147. };
  148. /** Occurs when a Widget begins consuming the Hover event.
  149. Must consume the Hover event to receive this event.
  150. The target sets `hoveredWidget`, which allows Leave to occur.
  151. */
  152. struct Enter : Base {
  153. };
  154. /** Occurs when a different Widget is entered.
  155. Must consume the Hover event (when a Widget is entered) to receive this event.
  156. */
  157. struct Leave : Base {
  158. };
  159. /** Occurs when a Widget begins consuming the Button press event for the left mouse button.
  160. Must consume the Button event (on left button press) to receive this event.
  161. The target sets `selectedWidget`, which allows SelectText and SelectKey to occur.
  162. */
  163. struct Select : Base {
  164. };
  165. /** Occurs when a different Widget is selected.
  166. Must consume the Button event (on left button press, when the Widget is selected) to receive this event.
  167. */
  168. struct Deselect : Base {
  169. };
  170. /** Occurs when a key is pressed, released, or repeated while a Widget is selected.
  171. Must consume to prevent HoverKey from being triggered.
  172. */
  173. struct SelectKey : Base, KeyBase {
  174. };
  175. /** Occurs when text is typed while a Widget is selected.
  176. Must consume to prevent HoverKey from being triggered.
  177. */
  178. struct SelectText : Base, TextBase {
  179. };
  180. struct DragBase : Base {
  181. /** The mouse button held while dragging. */
  182. int button;
  183. };
  184. /** Occurs when a Widget begins being dragged.
  185. Must consume the Button event (on press) to receive this event.
  186. The target sets `draggedWidget`, which allows DragEnd, DragMove, DragHover, DragEnter, and DragDrop to occur.
  187. */
  188. struct DragStart : DragBase {
  189. };
  190. /** Occurs when a Widget stops being dragged by releasing the mouse button.
  191. Must consume the Button event (on press, when the Widget drag begins) to receive this event.
  192. */
  193. struct DragEnd : DragBase {
  194. };
  195. /** Occurs every frame on the dragged Widget.
  196. Must consume the Button event (on press, when the Widget drag begins) to receive this event.
  197. */
  198. struct DragMove : DragBase {
  199. /** Change in mouse position since the last frame. Can be zero. */
  200. math::Vec mouseDelta;
  201. };
  202. /** Occurs every frame when the mouse is hovering over a Widget while another Widget (possibly the same one) is being dragged.
  203. Recurses.
  204. Consume this event to allow DragEnter and DragLeave to occur.
  205. */
  206. struct DragHover : DragBase, PositionBase {
  207. /** The dragged widget */
  208. widget::Widget* origin = NULL;
  209. /** Change in mouse position since the last frame. Can be zero. */
  210. math::Vec mouseDelta;
  211. };
  212. /** Occurs when the mouse enters a Widget while dragging.
  213. Must consume the DragHover event to receive this event.
  214. The target sets `draggedWidget`, which allows DragLeave to occur.
  215. */
  216. struct DragEnter : DragBase {
  217. /** The dragged widget */
  218. widget::Widget* origin = NULL;
  219. };
  220. /** Occurs when the mouse leaves a Widget while dragging.
  221. Must consume the DragHover event (when the Widget is entered) to receive this event.
  222. */
  223. struct DragLeave : DragBase {
  224. /** The dragged widget */
  225. widget::Widget* origin = NULL;
  226. };
  227. /** Occurs when the mouse button is released over a Widget while dragging.
  228. Must consume the Button event (on release) to receive this event.
  229. */
  230. struct DragDrop : DragBase {
  231. /** The dragged widget */
  232. widget::Widget* origin = NULL;
  233. };
  234. /** Occurs when a selection of files from the operating system is dropped onto a Widget.
  235. Recurses.
  236. */
  237. struct PathDrop : Base, PositionBase {
  238. PathDrop(const std::vector<std::string>& paths) : paths(paths) {}
  239. /** List of file paths in the dropped selection */
  240. const std::vector<std::string>& paths;
  241. };
  242. /** Occurs after a certain action is triggered on a Widget.
  243. The concept of an "action" is defined by the type of Widget.
  244. */
  245. struct Action : Base {
  246. };
  247. /** Occurs after the value of a Widget changes.
  248. The concept of a "value" is defined by the type of Widget.
  249. */
  250. struct Change : Base {
  251. };
  252. /** Occurs after the zoom level of a Widget is changed.
  253. Recurses.
  254. */
  255. struct Zoom : Base {
  256. };
  257. /** Occurs after a Widget's position is set by Widget::setPosition().
  258. */
  259. struct Reposition : Base {
  260. };
  261. /** Occurs after a Widget's size is set by Widget::setSize().
  262. */
  263. struct Resize : Base {
  264. };
  265. /** Occurs after a Widget is added to a parent.
  266. */
  267. struct Add : Base {
  268. };
  269. /** Occurs before a Widget is removed from its parent.
  270. */
  271. struct Remove : Base {
  272. };
  273. /** Occurs after a Widget is shown with Widget::show().
  274. Recurses.
  275. */
  276. struct Show : Base {
  277. };
  278. /** Occurs after a Widget is hidden with Widget::hide().
  279. Recurses.
  280. */
  281. struct Hide : Base {
  282. };
  283. struct State {
  284. widget::Widget* rootWidget = NULL;
  285. /** State widgets
  286. Don't set these directly unless you know what you're doing. Use the set*() methods instead.
  287. */
  288. widget::Widget* hoveredWidget = NULL;
  289. widget::Widget* draggedWidget = NULL;
  290. int dragButton = 0;
  291. widget::Widget* dragHoveredWidget = NULL;
  292. widget::Widget* selectedWidget = NULL;
  293. /** For double-clicking */
  294. double lastClickTime = -INFINITY;
  295. widget::Widget* lastClickedWidget = NULL;
  296. std::set<int> heldKeys;
  297. widget::Widget* getRootWidget() {
  298. return rootWidget;
  299. }
  300. widget::Widget* getHoveredWidget() {
  301. return hoveredWidget;
  302. }
  303. widget::Widget* getDraggedWidget() {
  304. return draggedWidget;
  305. }
  306. widget::Widget* getDragHoveredWidget() {
  307. return dragHoveredWidget;
  308. }
  309. widget::Widget* getSelectedWidget() {
  310. return selectedWidget;
  311. }
  312. void setHovered(widget::Widget* w);
  313. void setDragged(widget::Widget* w, int button);
  314. void setDragHovered(widget::Widget* w);
  315. void setSelected(widget::Widget* w);
  316. /** Prepares a widget for deletion */
  317. void finalizeWidget(widget::Widget* w);
  318. bool handleButton(math::Vec pos, int button, int action, int mods);
  319. bool handleHover(math::Vec pos, math::Vec mouseDelta);
  320. bool handleLeave();
  321. bool handleScroll(math::Vec pos, math::Vec scrollDelta);
  322. bool handleText(math::Vec pos, int codepoint);
  323. bool handleKey(math::Vec pos, int key, int scancode, int action, int mods);
  324. bool handleDrop(math::Vec pos, const std::vector<std::string>& paths);
  325. bool handleZoom();
  326. };
  327. } // namespace event
  328. } // namespace rack