| @@ -19,9 +19,9 @@ struct Window; | |||||
| struct PatchManager; | struct PatchManager; | ||||
| namespace event { | |||||
| struct State; | |||||
| } // namespace event | |||||
| namespace widget { | |||||
| struct EventState; | |||||
| } // namespace widget | |||||
| namespace app { | namespace app { | ||||
| @@ -31,7 +31,7 @@ struct Scene; | |||||
| /** Contains the application state */ | /** Contains the application state */ | ||||
| struct Context { | struct Context { | ||||
| event::State* event = NULL; | |||||
| widget::EventState* event = NULL; | |||||
| app::Scene* scene = NULL; | app::Scene* scene = NULL; | ||||
| engine::Engine* engine = NULL; | engine::Engine* engine = NULL; | ||||
| Window* window = NULL; | Window* window = NULL; | ||||
| @@ -1,449 +0,0 @@ | |||||
| #pragma once | |||||
| #include <vector> | |||||
| #include <set> | |||||
| #include <common.hpp> | |||||
| #include <math.hpp> | |||||
| /** Remaps Ctrl to Cmd on Mac | |||||
| Use this instead of GLFW_MOD_CONTROL, since Cmd should be used on Mac in place of Ctrl on Linux/Windows. | |||||
| */ | |||||
| #if defined ARCH_MAC | |||||
| #define RACK_MOD_CTRL GLFW_MOD_SUPER | |||||
| #define RACK_MOD_CTRL_NAME "⌘" | |||||
| #else | |||||
| #define RACK_MOD_CTRL GLFW_MOD_CONTROL | |||||
| #define RACK_MOD_CTRL_NAME "Ctrl" | |||||
| #endif | |||||
| #define RACK_MOD_SHIFT_NAME "Shift" | |||||
| #define RACK_MOD_ALT_NAME "Alt" | |||||
| /** Filters actual mod keys from the mod flags. | |||||
| Use this if you don't care about GLFW_MOD_CAPS_LOCK and GLFW_MOD_NUM_LOCK. | |||||
| Example usage: | |||||
| if ((e.mod & RACK_MOD_MASK) == (RACK_MOD_CTRL | GLFW_MOD_SHIFT)) ... | |||||
| */ | |||||
| #define RACK_MOD_MASK (GLFW_MOD_SHIFT | GLFW_MOD_CONTROL | GLFW_MOD_ALT | GLFW_MOD_SUPER) | |||||
| namespace rack { | |||||
| namespace widget { | |||||
| struct Widget; | |||||
| } | |||||
| /** Handles user interaction with Widget. | |||||
| */ | |||||
| namespace event { | |||||
| /** A per-event state shared and writable by all widgets that recursively handle an event. */ | |||||
| struct Context { | |||||
| /** Whether the event should continue recursing to children Widgets. */ | |||||
| bool propagating = true; | |||||
| /** Whether the event has been consumed by an event handler and no more handlers should consume the event. */ | |||||
| bool consumed = false; | |||||
| /** The widget that responded to the event. */ | |||||
| widget::Widget* target = NULL; | |||||
| }; | |||||
| /** Base class for all events. */ | |||||
| struct Base { | |||||
| Context* context = NULL; | |||||
| /** Prevents the event from being handled by more Widgets. | |||||
| */ | |||||
| void stopPropagating() const { | |||||
| if (!context) | |||||
| return; | |||||
| context->propagating = false; | |||||
| } | |||||
| bool isPropagating() const { | |||||
| if (!context) | |||||
| return true; | |||||
| return context->propagating; | |||||
| } | |||||
| /** Tells the event handler that a particular Widget consumed the event. | |||||
| You usually want to stop propagation as well, so call consume() instead. | |||||
| */ | |||||
| void setTarget(widget::Widget* w) const { | |||||
| if (!context) | |||||
| return; | |||||
| context->target = w; | |||||
| } | |||||
| widget::Widget* getTarget() const { | |||||
| if (!context) | |||||
| return NULL; | |||||
| return context->target; | |||||
| } | |||||
| /** Sets the target Widget and stops propagating. | |||||
| A NULL Widget may be passed to consume but not set a target. | |||||
| */ | |||||
| void consume(widget::Widget* w) const { | |||||
| if (!context) | |||||
| return; | |||||
| context->propagating = false; | |||||
| context->consumed = true; | |||||
| context->target = w; | |||||
| } | |||||
| void unconsume() const { | |||||
| if (!context) | |||||
| return; | |||||
| context->consumed = false; | |||||
| } | |||||
| bool isConsumed() const { | |||||
| if (!context) | |||||
| return false; | |||||
| return context->consumed; | |||||
| } | |||||
| }; | |||||
| /** An event prototype with a vector position. */ | |||||
| struct PositionBase { | |||||
| /** The pixel coordinate where the event occurred, relative to the Widget it is called on. */ | |||||
| math::Vec pos; | |||||
| }; | |||||
| #define RACK_HELD 3 | |||||
| /** An event prototype with a GLFW key. */ | |||||
| struct KeyBase { | |||||
| /** The key corresponding to what it would be called in its position on a QWERTY US keyboard. | |||||
| For example, the WASD directional keys used for first-person shooters will always be reported as "WASD", regardless if they say "ZQSD" on an AZERTY keyboard. | |||||
| You should usually not use these for printable characters such as "Ctrl+V" key commands. Instead, use `keyName`. | |||||
| You *should* use these for non-printable keys, such as Escape, arrow keys, Home, F1-12, etc. | |||||
| You should also use this for Enter, Tab, and Space. Although they are printable keys, they do not appear in `keyName`. | |||||
| See GLFW_KEY_* for the list of possible values. | |||||
| */ | |||||
| int key; | |||||
| /** Platform-dependent "software" key code. | |||||
| This variable is only included for completion. There should be no reason for you to use this. | |||||
| You should instead use `key` (for non-printable characters) or `keyName` (for printable characters). | |||||
| Values are platform independent and can change between different keyboards or keyboard layouts on the same OS. | |||||
| */ | |||||
| int scancode; | |||||
| /** String containing the lowercase key name, if it produces a printable character. | |||||
| This is the only variable that correctly represents the label printed on any keyboard layout, whether it's QWERTY, AZERTY, QWERTZ, Dvorak, etc. | |||||
| For example, if the user presses the key labeled "q" regardless of the key position, `keyName` will be "q". | |||||
| For non-printable characters this is an empty string. | |||||
| Enter, Tab, and Space do not give a `keyName`. Use `key` instead. | |||||
| Shift has no effect on the key name. Shift+1 results in "1", Shift+q results in "q", etc. | |||||
| */ | |||||
| std::string keyName; | |||||
| /** The type of event occurring with the key. | |||||
| Possible values are GLFW_RELEASE, GLFW_PRESS, GLFW_REPEAT, or RACK_HELD. | |||||
| RACK_HELD is sent every frame while the key is held. | |||||
| */ | |||||
| int action; | |||||
| /** Bitwise OR of key modifiers, such as Ctrl or Shift. | |||||
| Use (mods & RACK_MOD_MASK) == RACK_MOD_CTRL to check for Ctrl on Linux and Windows but Cmd on Mac. | |||||
| See GLFW_MOD_* for the list of possible values. | |||||
| */ | |||||
| int mods; | |||||
| }; | |||||
| /** An event prototype with a Unicode character. */ | |||||
| struct TextBase { | |||||
| /** Unicode code point of the character */ | |||||
| int codepoint; | |||||
| }; | |||||
| /** Occurs every frame when the mouse is hovering over a Widget. | |||||
| Recurses. | |||||
| Consume this event to allow Enter and Leave to occur. | |||||
| */ | |||||
| struct Hover : Base, PositionBase { | |||||
| /** Change in mouse position since the last frame. Can be zero. */ | |||||
| math::Vec mouseDelta; | |||||
| }; | |||||
| /** Occurs each mouse button press or release. | |||||
| Recurses. | |||||
| Consume this event to allow DoubleClick, Select, Deselect, SelectKey, SelectText, DragStart, DragEnd, DragMove, and DragDrop to occur. | |||||
| */ | |||||
| struct Button : Base, PositionBase { | |||||
| /** GLFW_MOUSE_BUTTON_LEFT, GLFW_MOUSE_BUTTON_RIGHT, GLFW_MOUSE_BUTTON_MIDDLE, etc. */ | |||||
| int button; | |||||
| /** GLFW_PRESS or GLFW_RELEASE */ | |||||
| int action; | |||||
| /** GLFW_MOD_* */ | |||||
| int mods; | |||||
| }; | |||||
| /** Occurs when the left mouse button is pressed a second time on the same Widget within a time duration. | |||||
| Must consume the Button event (on left button press) to receive this event. | |||||
| */ | |||||
| struct DoubleClick : Base { | |||||
| }; | |||||
| /** Occurs when a key is pressed, released, or repeated while the mouse is hovering a Widget. | |||||
| Recurses. | |||||
| */ | |||||
| struct HoverKey : Base, PositionBase, KeyBase { | |||||
| }; | |||||
| /** Occurs when a character is typed while the mouse is hovering a Widget. | |||||
| Recurses. | |||||
| */ | |||||
| struct HoverText : Base, PositionBase, TextBase { | |||||
| }; | |||||
| /** Occurs when the mouse scroll wheel is moved while the mouse is hovering a Widget. | |||||
| Recurses. | |||||
| */ | |||||
| struct HoverScroll : Base, PositionBase { | |||||
| /** Change of scroll wheel position. */ | |||||
| math::Vec scrollDelta; | |||||
| }; | |||||
| /** Occurs when a Widget begins consuming the Hover event. | |||||
| Must consume the Hover event to receive this event. | |||||
| The target sets `hoveredWidget`, which allows Leave to occur. | |||||
| */ | |||||
| struct Enter : Base { | |||||
| }; | |||||
| /** Occurs when a different Widget is entered. | |||||
| Must consume the Hover event (when a Widget is entered) to receive this event. | |||||
| */ | |||||
| struct Leave : Base { | |||||
| }; | |||||
| /** Occurs when a Widget begins consuming the Button press event for the left mouse button. | |||||
| Must consume the Button event (on left button press) to receive this event. | |||||
| The target sets `selectedWidget`, which allows SelectText and SelectKey to occur. | |||||
| */ | |||||
| struct Select : Base { | |||||
| }; | |||||
| /** Occurs when a different Widget is selected. | |||||
| Must consume the Button event (on left button press, when the Widget is selected) to receive this event. | |||||
| */ | |||||
| struct Deselect : Base { | |||||
| }; | |||||
| /** Occurs when a key is pressed, released, or repeated while a Widget is selected. | |||||
| Must consume to prevent HoverKey from being triggered. | |||||
| */ | |||||
| struct SelectKey : Base, KeyBase { | |||||
| }; | |||||
| /** Occurs when text is typed while a Widget is selected. | |||||
| Must consume to prevent HoverKey from being triggered. | |||||
| */ | |||||
| struct SelectText : Base, TextBase { | |||||
| }; | |||||
| struct DragBase : Base { | |||||
| /** The mouse button held while dragging. */ | |||||
| int button; | |||||
| }; | |||||
| /** Occurs when a Widget begins being dragged. | |||||
| Must consume the Button event (on press) to receive this event. | |||||
| The target sets `draggedWidget`, which allows DragEnd, DragMove, DragHover, DragEnter, and DragDrop to occur. | |||||
| */ | |||||
| struct DragStart : DragBase { | |||||
| }; | |||||
| /** Occurs when a Widget stops being dragged by releasing the mouse button. | |||||
| Must consume the Button event (on press, when the Widget drag begins) to receive this event. | |||||
| */ | |||||
| struct DragEnd : DragBase { | |||||
| }; | |||||
| /** Occurs every frame on the dragged Widget. | |||||
| Must consume the Button event (on press, when the Widget drag begins) to receive this event. | |||||
| */ | |||||
| struct DragMove : DragBase { | |||||
| /** Change in mouse position since the last frame. Can be zero. */ | |||||
| math::Vec mouseDelta; | |||||
| }; | |||||
| /** Occurs every frame when the mouse is hovering over a Widget while another Widget (possibly the same one) is being dragged. | |||||
| Recurses. | |||||
| Consume this event to allow DragEnter and DragLeave to occur. | |||||
| */ | |||||
| struct DragHover : DragBase, PositionBase { | |||||
| /** The dragged widget */ | |||||
| widget::Widget* origin = NULL; | |||||
| /** Change in mouse position since the last frame. Can be zero. */ | |||||
| math::Vec mouseDelta; | |||||
| }; | |||||
| /** Occurs when the mouse enters a Widget while dragging. | |||||
| Must consume the DragHover event to receive this event. | |||||
| The target sets `draggedWidget`, which allows DragLeave to occur. | |||||
| */ | |||||
| struct DragEnter : DragBase { | |||||
| /** The dragged widget */ | |||||
| widget::Widget* origin = NULL; | |||||
| }; | |||||
| /** Occurs when the mouse leaves a Widget while dragging. | |||||
| Must consume the DragHover event (when the Widget is entered) to receive this event. | |||||
| */ | |||||
| struct DragLeave : DragBase { | |||||
| /** The dragged widget */ | |||||
| widget::Widget* origin = NULL; | |||||
| }; | |||||
| /** Occurs when the mouse button is released over a Widget while dragging. | |||||
| Must consume the Button event (on release) to receive this event. | |||||
| */ | |||||
| struct DragDrop : DragBase { | |||||
| /** The dragged widget */ | |||||
| widget::Widget* origin = NULL; | |||||
| }; | |||||
| /** Occurs when a selection of files from the operating system is dropped onto a Widget. | |||||
| Recurses. | |||||
| */ | |||||
| struct PathDrop : Base, PositionBase { | |||||
| PathDrop(const std::vector<std::string>& paths) : paths(paths) {} | |||||
| /** List of file paths in the dropped selection */ | |||||
| const std::vector<std::string>& paths; | |||||
| }; | |||||
| /** Occurs after a certain action is triggered on a Widget. | |||||
| The concept of an "action" is defined by the type of Widget. | |||||
| */ | |||||
| struct Action : Base { | |||||
| }; | |||||
| /** Occurs after the value of a Widget changes. | |||||
| The concept of a "value" is defined by the type of Widget. | |||||
| */ | |||||
| struct Change : Base { | |||||
| }; | |||||
| /** Occurs when the pixel buffer of this module must be refreshed. | |||||
| Recurses. | |||||
| */ | |||||
| struct Dirty : Base { | |||||
| }; | |||||
| /** Occurs after a Widget's position is set by Widget::setPosition(). | |||||
| */ | |||||
| struct Reposition : Base { | |||||
| }; | |||||
| /** Occurs after a Widget's size is set by Widget::setSize(). | |||||
| */ | |||||
| struct Resize : Base { | |||||
| }; | |||||
| /** Occurs after a Widget is added to a parent. | |||||
| */ | |||||
| struct Add : Base { | |||||
| }; | |||||
| /** Occurs before a Widget is removed from its parent. | |||||
| */ | |||||
| struct Remove : Base { | |||||
| }; | |||||
| /** Occurs after a Widget is shown with Widget::show(). | |||||
| Recurses. | |||||
| */ | |||||
| struct Show : Base { | |||||
| }; | |||||
| /** Occurs after a Widget is hidden with Widget::hide(). | |||||
| Recurses. | |||||
| */ | |||||
| struct Hide : Base { | |||||
| }; | |||||
| struct State { | |||||
| widget::Widget* rootWidget = NULL; | |||||
| /** State widgets | |||||
| Don't set these directly unless you know what you're doing. Use the set*() methods instead. | |||||
| */ | |||||
| widget::Widget* hoveredWidget = NULL; | |||||
| widget::Widget* draggedWidget = NULL; | |||||
| int dragButton = 0; | |||||
| widget::Widget* dragHoveredWidget = NULL; | |||||
| widget::Widget* selectedWidget = NULL; | |||||
| /** For double-clicking */ | |||||
| double lastClickTime = -INFINITY; | |||||
| widget::Widget* lastClickedWidget = NULL; | |||||
| std::set<int> heldKeys; | |||||
| widget::Widget* getRootWidget() { | |||||
| return rootWidget; | |||||
| } | |||||
| widget::Widget* getHoveredWidget() { | |||||
| return hoveredWidget; | |||||
| } | |||||
| widget::Widget* getDraggedWidget() { | |||||
| return draggedWidget; | |||||
| } | |||||
| widget::Widget* getDragHoveredWidget() { | |||||
| return dragHoveredWidget; | |||||
| } | |||||
| widget::Widget* getSelectedWidget() { | |||||
| return selectedWidget; | |||||
| } | |||||
| void setHovered(widget::Widget* w); | |||||
| void setDragged(widget::Widget* w, int button); | |||||
| void setDragHovered(widget::Widget* w); | |||||
| void setSelected(widget::Widget* w); | |||||
| /** Prepares a widget for deletion */ | |||||
| void finalizeWidget(widget::Widget* w); | |||||
| bool handleButton(math::Vec pos, int button, int action, int mods); | |||||
| bool handleHover(math::Vec pos, math::Vec mouseDelta); | |||||
| bool handleLeave(); | |||||
| bool handleScroll(math::Vec pos, math::Vec scrollDelta); | |||||
| bool handleText(math::Vec pos, int codepoint); | |||||
| bool handleKey(math::Vec pos, int key, int scancode, int action, int mods); | |||||
| bool handleDrop(math::Vec pos, const std::vector<std::string>& paths); | |||||
| bool handleDirty(); | |||||
| }; | |||||
| } // namespace event | |||||
| } // namespace rack | |||||
| @@ -16,6 +16,7 @@ | |||||
| #include <helpers.hpp> | #include <helpers.hpp> | ||||
| #include <componentlibrary.hpp> | #include <componentlibrary.hpp> | ||||
| #include <widget/event.hpp> | |||||
| #include <widget/Widget.hpp> | #include <widget/Widget.hpp> | ||||
| #include <widget/TransparentWidget.hpp> | #include <widget/TransparentWidget.hpp> | ||||
| #include <widget/OpaqueWidget.hpp> | #include <widget/OpaqueWidget.hpp> | ||||
| @@ -3,7 +3,6 @@ | |||||
| #include <widget/OpaqueWidget.hpp> | #include <widget/OpaqueWidget.hpp> | ||||
| #include <Quantity.hpp> | #include <Quantity.hpp> | ||||
| #include <context.hpp> | #include <context.hpp> | ||||
| #include <event.hpp> | |||||
| namespace rack { | namespace rack { | ||||
| @@ -5,7 +5,7 @@ | |||||
| #include <math.hpp> | #include <math.hpp> | ||||
| #include <window.hpp> | #include <window.hpp> | ||||
| #include <color.hpp> | #include <color.hpp> | ||||
| #include <event.hpp> | |||||
| #include <widget/event.hpp> | |||||
| #include <weakptr.hpp> | #include <weakptr.hpp> | ||||
| @@ -168,60 +168,333 @@ struct Widget : WeakBase { | |||||
| } | } | ||||
| } | } | ||||
| /** Override these event callbacks to respond to events. | |||||
| See event.hpp for a description of each event. | |||||
| using BaseEvent = widget::BaseEvent; | |||||
| /** An event prototype with a vector position. */ | |||||
| struct PositionBaseEvent { | |||||
| /** The pixel coordinate where the event occurred, relative to the Widget it is called on. */ | |||||
| math::Vec pos; | |||||
| }; | |||||
| /** Occurs every frame when the mouse is hovering over a Widget. | |||||
| Recurses. | |||||
| Consume this event to allow Enter and Leave to occur. | |||||
| */ | */ | ||||
| virtual void onHover(const event::Hover& e) { | |||||
| struct HoverEvent : BaseEvent, PositionBaseEvent { | |||||
| /** Change in mouse position since the last frame. Can be zero. */ | |||||
| math::Vec mouseDelta; | |||||
| }; | |||||
| virtual void onHover(const HoverEvent& e) { | |||||
| recursePositionEvent(&Widget::onHover, e); | recursePositionEvent(&Widget::onHover, e); | ||||
| } | } | ||||
| virtual void onButton(const event::Button& e) { | |||||
| /** Occurs each mouse button press or release. | |||||
| Recurses. | |||||
| Consume this event to allow DoubleClick, Select, Deselect, SelectKey, SelectText, DragStart, DragEnd, DragMove, and DragDrop to occur. | |||||
| */ | |||||
| struct ButtonEvent : BaseEvent, PositionBaseEvent { | |||||
| /** GLFW_MOUSE_BUTTON_LEFT, GLFW_MOUSE_BUTTON_RIGHT, GLFW_MOUSE_BUTTON_MIDDLE, etc. */ | |||||
| int button; | |||||
| /** GLFW_PRESS or GLFW_RELEASE */ | |||||
| int action; | |||||
| /** GLFW_MOD_* */ | |||||
| int mods; | |||||
| }; | |||||
| virtual void onButton(const ButtonEvent& e) { | |||||
| recursePositionEvent(&Widget::onButton, e); | recursePositionEvent(&Widget::onButton, e); | ||||
| } | } | ||||
| virtual void onDoubleClick(const event::DoubleClick& e) {} | |||||
| virtual void onHoverKey(const event::HoverKey& e) { | |||||
| /** Occurs when the left mouse button is pressed a second time on the same Widget within a time duration. | |||||
| Must consume the Button event (on left button press) to receive this event. | |||||
| */ | |||||
| struct DoubleClickEvent : BaseEvent {}; | |||||
| virtual void onDoubleClick(const DoubleClickEvent& e) {} | |||||
| /** An event prototype with a GLFW key. */ | |||||
| struct KeyBaseEvent { | |||||
| /** The key corresponding to what it would be called in its position on a QWERTY US keyboard. | |||||
| For example, the WASD directional keys used for first-person shooters will always be reported as "WASD", regardless if they say "ZQSD" on an AZERTY keyboard. | |||||
| You should usually not use these for printable characters such as "Ctrl+V" key commands. Instead, use `keyName`. | |||||
| You *should* use these for non-printable keys, such as Escape, arrow keys, Home, F1-12, etc. | |||||
| You should also use this for Enter, Tab, and Space. Although they are printable keys, they do not appear in `keyName`. | |||||
| See GLFW_KEY_* for the list of possible values. | |||||
| */ | |||||
| int key; | |||||
| /** Platform-dependent "software" key code. | |||||
| This variable is only included for completion. There should be no reason for you to use this. | |||||
| You should instead use `key` (for non-printable characters) or `keyName` (for printable characters). | |||||
| Values are platform independent and can change between different keyboards or keyboard layouts on the same OS. | |||||
| */ | |||||
| int scancode; | |||||
| /** String containing the lowercase key name, if it produces a printable character. | |||||
| This is the only variable that correctly represents the label printed on any keyboard layout, whether it's QWERTY, AZERTY, QWERTZ, Dvorak, etc. | |||||
| For example, if the user presses the key labeled "q" regardless of the key position, `keyName` will be "q". | |||||
| For non-printable characters this is an empty string. | |||||
| Enter, Tab, and Space do not give a `keyName`. Use `key` instead. | |||||
| Shift has no effect on the key name. Shift+1 results in "1", Shift+q results in "q", etc. | |||||
| */ | |||||
| std::string keyName; | |||||
| /** The type of event occurring with the key. | |||||
| Possible values are GLFW_RELEASE, GLFW_PRESS, GLFW_REPEAT, or RACK_HELD. | |||||
| RACK_HELD is sent every frame while the key is held. | |||||
| */ | |||||
| int action; | |||||
| /** Bitwise OR of key modifiers, such as Ctrl or Shift. | |||||
| Use (mods & RACK_MOD_MASK) == RACK_MOD_CTRL to check for Ctrl on Linux and Windows but Cmd on Mac. | |||||
| See GLFW_MOD_* for the list of possible values. | |||||
| */ | |||||
| int mods; | |||||
| }; | |||||
| /** Occurs when a key is pressed, released, or repeated while the mouse is hovering a Widget. | |||||
| Recurses. | |||||
| */ | |||||
| struct HoverKeyEvent : BaseEvent, PositionBaseEvent, KeyBaseEvent {}; | |||||
| virtual void onHoverKey(const HoverKeyEvent& e) { | |||||
| recursePositionEvent(&Widget::onHoverKey, e); | recursePositionEvent(&Widget::onHoverKey, e); | ||||
| } | } | ||||
| virtual void onHoverText(const event::HoverText& e) { | |||||
| /** An event prototype with a Unicode character. */ | |||||
| struct TextBaseEvent { | |||||
| /** Unicode code point of the character */ | |||||
| int codepoint; | |||||
| }; | |||||
| /** Occurs when a character is typed while the mouse is hovering a Widget. | |||||
| Recurses. | |||||
| */ | |||||
| struct HoverTextEvent : BaseEvent, PositionBaseEvent, TextBaseEvent {}; | |||||
| virtual void onHoverText(const HoverTextEvent& e) { | |||||
| recursePositionEvent(&Widget::onHoverText, e); | recursePositionEvent(&Widget::onHoverText, e); | ||||
| } | } | ||||
| virtual void onHoverScroll(const event::HoverScroll& e) { | |||||
| /** Occurs when the mouse scroll wheel is moved while the mouse is hovering a Widget. | |||||
| Recurses. | |||||
| */ | |||||
| struct HoverScrollEvent : BaseEvent, PositionBaseEvent { | |||||
| /** Change of scroll wheel position. */ | |||||
| math::Vec scrollDelta; | |||||
| }; | |||||
| virtual void onHoverScroll(const HoverScrollEvent& e) { | |||||
| recursePositionEvent(&Widget::onHoverScroll, e); | recursePositionEvent(&Widget::onHoverScroll, e); | ||||
| } | } | ||||
| virtual void onEnter(const event::Enter& e) {} | |||||
| virtual void onLeave(const event::Leave& e) {} | |||||
| virtual void onSelect(const event::Select& e) {} | |||||
| virtual void onDeselect(const event::Deselect& e) {} | |||||
| virtual void onSelectKey(const event::SelectKey& e) {} | |||||
| virtual void onSelectText(const event::SelectText& e) {} | |||||
| virtual void onDragStart(const event::DragStart& e) {} | |||||
| virtual void onDragEnd(const event::DragEnd& e) {} | |||||
| virtual void onDragMove(const event::DragMove& e) {} | |||||
| virtual void onDragHover(const event::DragHover& e) { | |||||
| /** Occurs when a Widget begins consuming the Hover event. | |||||
| Must consume the Hover event to receive this event. | |||||
| The target sets `hoveredWidget`, which allows Leave to occur. | |||||
| */ | |||||
| struct EnterEvent : BaseEvent {}; | |||||
| virtual void onEnter(const EnterEvent& e) {} | |||||
| /** Occurs when a different Widget is entered. | |||||
| Must consume the Hover event (when a Widget is entered) to receive this event. | |||||
| */ | |||||
| struct LeaveEvent : BaseEvent {}; | |||||
| virtual void onLeave(const LeaveEvent& e) {} | |||||
| /** Occurs when a Widget begins consuming the Button press event for the left mouse button. | |||||
| Must consume the Button event (on left button press) to receive this event. | |||||
| The target sets `selectedWidget`, which allows SelectText and SelectKey to occur. | |||||
| */ | |||||
| struct SelectEvent : BaseEvent {}; | |||||
| virtual void onSelect(const SelectEvent& e) {} | |||||
| /** Occurs when a different Widget is selected. | |||||
| Must consume the Button event (on left button press, when the Widget is selected) to receive this event. | |||||
| */ | |||||
| struct DeselectEvent : BaseEvent {}; | |||||
| virtual void onDeselect(const DeselectEvent& e) {} | |||||
| /** Occurs when a key is pressed, released, or repeated while a Widget is selected. | |||||
| Must consume to prevent HoverKey from being triggered. | |||||
| */ | |||||
| struct SelectKeyEvent : BaseEvent, KeyBaseEvent {}; | |||||
| virtual void onSelectKey(const SelectKeyEvent& e) {} | |||||
| /** Occurs when text is typed while a Widget is selected. | |||||
| Must consume to prevent HoverKey from being triggered. | |||||
| */ | |||||
| struct SelectTextEvent : BaseEvent, TextBaseEvent {}; | |||||
| virtual void onSelectText(const SelectTextEvent& e) {} | |||||
| struct DragBaseEvent : BaseEvent { | |||||
| /** The mouse button held while dragging. */ | |||||
| int button; | |||||
| }; | |||||
| /** Occurs when a Widget begins being dragged. | |||||
| Must consume the Button event (on press) to receive this event. | |||||
| The target sets `draggedWidget`, which allows DragEnd, DragMove, DragHover, DragEnter, and DragDrop to occur. | |||||
| */ | |||||
| struct DragStartEvent : DragBaseEvent {}; | |||||
| virtual void onDragStart(const DragStartEvent& e) {} | |||||
| /** Occurs when a Widget stops being dragged by releasing the mouse button. | |||||
| Must consume the Button event (on press, when the Widget drag begins) to receive this event. | |||||
| */ | |||||
| struct DragEndEvent : DragBaseEvent {}; | |||||
| virtual void onDragEnd(const DragEndEvent& e) {} | |||||
| /** Occurs every frame on the dragged Widget. | |||||
| Must consume the Button event (on press, when the Widget drag begins) to receive this event. | |||||
| */ | |||||
| struct DragMoveEvent : DragBaseEvent { | |||||
| /** Change in mouse position since the last frame. Can be zero. */ | |||||
| math::Vec mouseDelta; | |||||
| }; | |||||
| virtual void onDragMove(const DragMoveEvent& e) {} | |||||
| /** Occurs every frame when the mouse is hovering over a Widget while another Widget (possibly the same one) is being dragged. | |||||
| Recurses. | |||||
| Consume this event to allow DragEnter and DragLeave to occur. | |||||
| */ | |||||
| struct DragHoverEvent : DragBaseEvent, PositionBaseEvent { | |||||
| /** The dragged widget */ | |||||
| Widget* origin = NULL; | |||||
| /** Change in mouse position since the last frame. Can be zero. */ | |||||
| math::Vec mouseDelta; | |||||
| }; | |||||
| virtual void onDragHover(const DragHoverEvent& e) { | |||||
| recursePositionEvent(&Widget::onDragHover, e); | recursePositionEvent(&Widget::onDragHover, e); | ||||
| } | } | ||||
| virtual void onDragEnter(const event::DragEnter& e) {} | |||||
| virtual void onDragLeave(const event::DragLeave& e) {} | |||||
| virtual void onDragDrop(const event::DragDrop& e) {} | |||||
| virtual void onPathDrop(const event::PathDrop& e) { | |||||
| /** Occurs when the mouse enters a Widget while dragging. | |||||
| Must consume the DragHover event to receive this event. | |||||
| The target sets `draggedWidget`, which allows DragLeave to occur. | |||||
| */ | |||||
| struct DragEnterEvent : DragBaseEvent { | |||||
| /** The dragged widget */ | |||||
| Widget* origin = NULL; | |||||
| }; | |||||
| virtual void onDragEnter(const DragEnterEvent& e) {} | |||||
| /** Occurs when the mouse leaves a Widget while dragging. | |||||
| Must consume the DragHover event (when the Widget is entered) to receive this event. | |||||
| */ | |||||
| struct DragLeaveEvent : DragBaseEvent { | |||||
| /** The dragged widget */ | |||||
| Widget* origin = NULL; | |||||
| }; | |||||
| virtual void onDragLeave(const DragLeaveEvent& e) {} | |||||
| /** Occurs when the mouse button is released over a Widget while dragging. | |||||
| Must consume the Button event (on release) to receive this event. | |||||
| */ | |||||
| struct DragDropEvent : DragBaseEvent { | |||||
| /** The dragged widget */ | |||||
| Widget* origin = NULL; | |||||
| }; | |||||
| virtual void onDragDrop(const DragDropEvent& e) {} | |||||
| /** Occurs when a selection of files from the operating system is dropped onto a Widget. | |||||
| Recurses. | |||||
| */ | |||||
| struct PathDropEvent : BaseEvent, PositionBaseEvent { | |||||
| PathDropEvent(const std::vector<std::string>& paths) : paths(paths) {} | |||||
| /** List of file paths in the dropped selection */ | |||||
| const std::vector<std::string>& paths; | |||||
| }; | |||||
| virtual void onPathDrop(const PathDropEvent& e) { | |||||
| recursePositionEvent(&Widget::onPathDrop, e); | recursePositionEvent(&Widget::onPathDrop, e); | ||||
| } | } | ||||
| virtual void onAction(const event::Action& e) {} | |||||
| virtual void onChange(const event::Change& e) {} | |||||
| virtual void onDirty(const event::Dirty& e) { | |||||
| /** Occurs after a certain action is triggered on a Widget. | |||||
| The concept of an "action" is defined by the type of Widget. | |||||
| */ | |||||
| struct ActionEvent : BaseEvent {}; | |||||
| virtual void onAction(const ActionEvent& e) {} | |||||
| /** Occurs after the value of a Widget changes. | |||||
| The concept of a "value" is defined by the type of Widget. | |||||
| */ | |||||
| struct ChangeEvent : BaseEvent {}; | |||||
| virtual void onChange(const ChangeEvent& e) {} | |||||
| /** Occurs when the pixel buffer of this module must be refreshed. | |||||
| Recurses. | |||||
| */ | |||||
| struct DirtyEvent : BaseEvent {}; | |||||
| virtual void onDirty(const DirtyEvent& e) { | |||||
| recurseEvent(&Widget::onDirty, e); | recurseEvent(&Widget::onDirty, e); | ||||
| } | } | ||||
| virtual void onReposition(const event::Reposition& e) {} | |||||
| virtual void onResize(const event::Resize& e) {} | |||||
| virtual void onAdd(const event::Add& e) {} | |||||
| virtual void onRemove(const event::Remove& e) {} | |||||
| virtual void onShow(const event::Show& e) { | |||||
| /** Occurs after a Widget's position is set by Widget::setPosition(). | |||||
| */ | |||||
| struct RepositionEvent : BaseEvent {}; | |||||
| virtual void onReposition(const RepositionEvent& e) {} | |||||
| /** Occurs after a Widget's size is set by Widget::setSize(). | |||||
| */ | |||||
| struct ResizeEvent : BaseEvent {}; | |||||
| virtual void onResize(const ResizeEvent& e) {} | |||||
| /** Occurs after a Widget is added to a parent. | |||||
| */ | |||||
| struct AddEvent : BaseEvent {}; | |||||
| virtual void onAdd(const AddEvent& e) {} | |||||
| /** Occurs before a Widget is removed from its parent. | |||||
| */ | |||||
| struct RemoveEvent : BaseEvent {}; | |||||
| virtual void onRemove(const RemoveEvent& e) {} | |||||
| /** Occurs after a Widget is shown with Widget::show(). | |||||
| Recurses. | |||||
| */ | |||||
| struct ShowEvent : BaseEvent {}; | |||||
| virtual void onShow(const ShowEvent& e) { | |||||
| recurseEvent(&Widget::onShow, e); | recurseEvent(&Widget::onShow, e); | ||||
| } | } | ||||
| virtual void onHide(const event::Hide& e) { | |||||
| /** Occurs after a Widget is hidden with Widget::hide(). | |||||
| Recurses. | |||||
| */ | |||||
| struct HideEvent : BaseEvent {}; | |||||
| virtual void onHide(const HideEvent& e) { | |||||
| recurseEvent(&Widget::onHide, e); | recurseEvent(&Widget::onHide, e); | ||||
| } | } | ||||
| }; | }; | ||||
| } // namespace widget | } // namespace widget | ||||
| /** Deprecated Rack v1 event namespace. | |||||
| Use `ExampleWidget` instead of `event::Example` in new code. | |||||
| */ | |||||
| namespace event { | |||||
| using Base = widget::BaseEvent; | |||||
| using PositionBase = widget::Widget::PositionBaseEvent; | |||||
| using KeyBase = widget::Widget::KeyBaseEvent; | |||||
| using TextBase = widget::Widget::TextBaseEvent; | |||||
| using Hover = widget::Widget::HoverEvent; | |||||
| using Button = widget::Widget::ButtonEvent; | |||||
| using DoubleClick = widget::Widget::DoubleClickEvent; | |||||
| using HoverKey = widget::Widget::HoverKeyEvent; | |||||
| using HoverText = widget::Widget::HoverTextEvent; | |||||
| using HoverScroll = widget::Widget::HoverScrollEvent; | |||||
| using Enter = widget::Widget::EnterEvent; | |||||
| using Leave = widget::Widget::LeaveEvent; | |||||
| using Select = widget::Widget::SelectEvent; | |||||
| using Deselect = widget::Widget::DeselectEvent; | |||||
| using SelectKey = widget::Widget::SelectKeyEvent; | |||||
| using SelectText = widget::Widget::SelectTextEvent; | |||||
| using DragBase = widget::Widget::DragBaseEvent; | |||||
| using DragStart = widget::Widget::DragStartEvent; | |||||
| using DragEnd = widget::Widget::DragEndEvent; | |||||
| using DragMove = widget::Widget::DragMoveEvent; | |||||
| using DragHover = widget::Widget::DragHoverEvent; | |||||
| using DragEnter = widget::Widget::DragEnterEvent; | |||||
| using DragLeave = widget::Widget::DragLeaveEvent; | |||||
| using DragDrop = widget::Widget::DragDropEvent; | |||||
| using PathDrop = widget::Widget::PathDropEvent; | |||||
| using Action = widget::Widget::ActionEvent; | |||||
| using Change = widget::Widget::ChangeEvent; | |||||
| using Dirty = widget::Widget::DirtyEvent; | |||||
| using Reposition = widget::Widget::RepositionEvent; | |||||
| using Resize = widget::Widget::ResizeEvent; | |||||
| using Add = widget::Widget::AddEvent; | |||||
| using Remove = widget::Widget::RemoveEvent; | |||||
| using Show = widget::Widget::ShowEvent; | |||||
| using Hide = widget::Widget::HideEvent; | |||||
| } | |||||
| } // namespace rack | } // namespace rack | ||||
| @@ -0,0 +1,155 @@ | |||||
| #pragma once | |||||
| #include <vector> | |||||
| #include <set> | |||||
| #include <common.hpp> | |||||
| #include <math.hpp> | |||||
| /** Remaps Ctrl to Cmd on Mac | |||||
| Use this instead of GLFW_MOD_CONTROL, since Cmd should be used on Mac in place of Ctrl on Linux/Windows. | |||||
| */ | |||||
| #if defined ARCH_MAC | |||||
| #define RACK_MOD_CTRL GLFW_MOD_SUPER | |||||
| #define RACK_MOD_CTRL_NAME "⌘" | |||||
| #else | |||||
| #define RACK_MOD_CTRL GLFW_MOD_CONTROL | |||||
| #define RACK_MOD_CTRL_NAME "Ctrl" | |||||
| #endif | |||||
| #define RACK_MOD_SHIFT_NAME "Shift" | |||||
| #define RACK_MOD_ALT_NAME "Alt" | |||||
| /** Filters actual mod keys from the mod flags. | |||||
| Use this if you don't care about GLFW_MOD_CAPS_LOCK and GLFW_MOD_NUM_LOCK. | |||||
| Example usage: | |||||
| if ((e.mod & RACK_MOD_MASK) == (RACK_MOD_CTRL | GLFW_MOD_SHIFT)) ... | |||||
| */ | |||||
| #define RACK_MOD_MASK (GLFW_MOD_SHIFT | GLFW_MOD_CONTROL | GLFW_MOD_ALT | GLFW_MOD_SUPER) | |||||
| /** A key action state representing the the key is (still) being held. | |||||
| */ | |||||
| #define RACK_HELD 3 | |||||
| namespace rack { | |||||
| namespace widget { | |||||
| struct Widget; | |||||
| /** A per-event state shared and writable by all widgets that recursively handle an event. */ | |||||
| struct EventContext { | |||||
| /** Whether the event should continue recursing to children Widgets. */ | |||||
| bool propagating = true; | |||||
| /** Whether the event has been consumed by an event handler and no more handlers should consume the event. */ | |||||
| bool consumed = false; | |||||
| /** The widget that responded to the event. */ | |||||
| Widget* target = NULL; | |||||
| }; | |||||
| /** Base class for all events. */ | |||||
| struct BaseEvent { | |||||
| EventContext* context = NULL; | |||||
| /** Prevents the event from being handled by more Widgets. | |||||
| */ | |||||
| void stopPropagating() const { | |||||
| if (!context) | |||||
| return; | |||||
| context->propagating = false; | |||||
| } | |||||
| bool isPropagating() const { | |||||
| if (!context) | |||||
| return true; | |||||
| return context->propagating; | |||||
| } | |||||
| /** Tells the event handler that a particular Widget consumed the event. | |||||
| You usually want to stop propagation as well, so call consume() instead. | |||||
| */ | |||||
| void setTarget(Widget* w) const { | |||||
| if (!context) | |||||
| return; | |||||
| context->target = w; | |||||
| } | |||||
| Widget* getTarget() const { | |||||
| if (!context) | |||||
| return NULL; | |||||
| return context->target; | |||||
| } | |||||
| /** Sets the target Widget and stops propagating. | |||||
| A NULL Widget may be passed to consume but not set a target. | |||||
| */ | |||||
| void consume(Widget* w) const { | |||||
| if (!context) | |||||
| return; | |||||
| context->propagating = false; | |||||
| context->consumed = true; | |||||
| context->target = w; | |||||
| } | |||||
| void unconsume() const { | |||||
| if (!context) | |||||
| return; | |||||
| context->consumed = false; | |||||
| } | |||||
| bool isConsumed() const { | |||||
| if (!context) | |||||
| return false; | |||||
| return context->consumed; | |||||
| } | |||||
| }; | |||||
| struct EventState { | |||||
| Widget* rootWidget = NULL; | |||||
| /** State widgets | |||||
| Don't set these directly unless you know what you're doing. Use the set*() methods instead. | |||||
| */ | |||||
| Widget* hoveredWidget = NULL; | |||||
| Widget* draggedWidget = NULL; | |||||
| int dragButton = 0; | |||||
| Widget* dragHoveredWidget = NULL; | |||||
| Widget* selectedWidget = NULL; | |||||
| /** For double-clicking */ | |||||
| double lastClickTime = -INFINITY; | |||||
| Widget* lastClickedWidget = NULL; | |||||
| std::set<int> heldKeys; | |||||
| Widget* getRootWidget() { | |||||
| return rootWidget; | |||||
| } | |||||
| Widget* getHoveredWidget() { | |||||
| return hoveredWidget; | |||||
| } | |||||
| Widget* getDraggedWidget() { | |||||
| return draggedWidget; | |||||
| } | |||||
| Widget* getDragHoveredWidget() { | |||||
| return dragHoveredWidget; | |||||
| } | |||||
| Widget* getSelectedWidget() { | |||||
| return selectedWidget; | |||||
| } | |||||
| void setHovered(Widget* w); | |||||
| void setDragged(Widget* w, int button); | |||||
| void setDragHovered(Widget* w); | |||||
| void setSelected(Widget* w); | |||||
| /** Prepares a widget for deletion */ | |||||
| void finalizeWidget(Widget* w); | |||||
| bool handleButton(math::Vec pos, int button, int action, int mods); | |||||
| bool handleHover(math::Vec pos, math::Vec mouseDelta); | |||||
| bool handleLeave(); | |||||
| bool handleScroll(math::Vec pos, math::Vec scrollDelta); | |||||
| bool handleText(math::Vec pos, int codepoint); | |||||
| bool handleKey(math::Vec pos, int key, int scancode, int action, int mods); | |||||
| bool handleDrop(math::Vec pos, const std::vector<std::string>& paths); | |||||
| bool handleDirty(); | |||||
| }; | |||||
| } // namespace widget | |||||
| } // namespace rack | |||||
| @@ -5,7 +5,6 @@ | |||||
| #include <context.hpp> | #include <context.hpp> | ||||
| #include <patch.hpp> | #include <patch.hpp> | ||||
| #include <settings.hpp> | #include <settings.hpp> | ||||
| #include <event.hpp> | |||||
| #include <engine/Engine.hpp> | #include <engine/Engine.hpp> | ||||
| #include <engine/Port.hpp> | #include <engine/Port.hpp> | ||||
| @@ -1,6 +1,5 @@ | |||||
| #include <ui/Button.hpp> | #include <ui/Button.hpp> | ||||
| #include <context.hpp> | #include <context.hpp> | ||||
| #include <event.hpp> | |||||
| namespace rack { | namespace rack { | ||||
| @@ -1,6 +1,5 @@ | |||||
| #include <ui/ChoiceButton.hpp> | #include <ui/ChoiceButton.hpp> | ||||
| #include <context.hpp> | #include <context.hpp> | ||||
| #include <event.hpp> | |||||
| namespace rack { | namespace rack { | ||||
| @@ -70,7 +70,7 @@ void MenuItem::doAction() { | |||||
| if (disabled) | if (disabled) | ||||
| return; | return; | ||||
| event::Context cAction; | |||||
| widget::EventContext cAction; | |||||
| event::Action eAction; | event::Action eAction; | ||||
| eAction.context = &cAction; | eAction.context = &cAction; | ||||
| // Consume event by default, but allow action to un-consume it to prevent the menu from being removed. | // Consume event by default, but allow action to un-consume it to prevent the menu from being removed. | ||||
| @@ -33,7 +33,7 @@ void ZoomWidget::setZoom(float zoom) { | |||||
| this->zoom = zoom; | this->zoom = zoom; | ||||
| // Trigger Dirty event | // Trigger Dirty event | ||||
| event::Context cDirty; | |||||
| widget::EventContext cDirty; | |||||
| event::Dirty eDirty; | event::Dirty eDirty; | ||||
| eDirty.context = &cDirty; | eDirty.context = &cDirty; | ||||
| Widget::onDirty(eDirty); | Widget::onDirty(eDirty); | ||||
| @@ -1,42 +1,42 @@ | |||||
| #include <event.hpp> | |||||
| #include <widget/event.hpp> | |||||
| #include <widget/Widget.hpp> | #include <widget/Widget.hpp> | ||||
| #include <context.hpp> | #include <context.hpp> | ||||
| #include <window.hpp> | #include <window.hpp> | ||||
| namespace rack { | namespace rack { | ||||
| namespace event { | |||||
| namespace widget { | |||||
| void State::setHovered(widget::Widget* w) { | |||||
| void EventState::setHovered(widget::Widget* w) { | |||||
| if (w == hoveredWidget) | if (w == hoveredWidget) | ||||
| return; | return; | ||||
| if (hoveredWidget) { | if (hoveredWidget) { | ||||
| // Trigger Leave event | |||||
| Leave eLeave; | |||||
| // Trigger LeaveEvent | |||||
| Widget::LeaveEvent eLeave; | |||||
| hoveredWidget->onLeave(eLeave); | hoveredWidget->onLeave(eLeave); | ||||
| hoveredWidget = NULL; | hoveredWidget = NULL; | ||||
| } | } | ||||
| if (w) { | if (w) { | ||||
| // Trigger Enter event | |||||
| Context cEnter; | |||||
| // Trigger EnterEvent | |||||
| EventContext cEnter; | |||||
| cEnter.target = w; | cEnter.target = w; | ||||
| Enter eEnter; | |||||
| Widget::EnterEvent eEnter; | |||||
| eEnter.context = &cEnter; | eEnter.context = &cEnter; | ||||
| w->onEnter(eEnter); | w->onEnter(eEnter); | ||||
| hoveredWidget = cEnter.target; | hoveredWidget = cEnter.target; | ||||
| } | } | ||||
| } | } | ||||
| void State::setDragged(widget::Widget* w, int button) { | |||||
| void EventState::setDragged(widget::Widget* w, int button) { | |||||
| if (w == draggedWidget) | if (w == draggedWidget) | ||||
| return; | return; | ||||
| if (draggedWidget) { | if (draggedWidget) { | ||||
| // Trigger DragEnd event | |||||
| DragEnd eDragEnd; | |||||
| // Trigger DragEndEvent | |||||
| Widget::DragEndEvent eDragEnd; | |||||
| eDragEnd.button = dragButton; | eDragEnd.button = dragButton; | ||||
| draggedWidget->onDragEnd(eDragEnd); | draggedWidget->onDragEnd(eDragEnd); | ||||
| draggedWidget = NULL; | draggedWidget = NULL; | ||||
| @@ -45,10 +45,10 @@ void State::setDragged(widget::Widget* w, int button) { | |||||
| dragButton = button; | dragButton = button; | ||||
| if (w) { | if (w) { | ||||
| // Trigger DragStart event | |||||
| Context cDragStart; | |||||
| // Trigger DragStartEvent | |||||
| EventContext cDragStart; | |||||
| cDragStart.target = w; | cDragStart.target = w; | ||||
| DragStart eDragStart; | |||||
| Widget::DragStartEvent eDragStart; | |||||
| eDragStart.context = &cDragStart; | eDragStart.context = &cDragStart; | ||||
| eDragStart.button = dragButton; | eDragStart.button = dragButton; | ||||
| w->onDragStart(eDragStart); | w->onDragStart(eDragStart); | ||||
| @@ -56,13 +56,13 @@ void State::setDragged(widget::Widget* w, int button) { | |||||
| } | } | ||||
| } | } | ||||
| void State::setDragHovered(widget::Widget* w) { | |||||
| void EventState::setDragHovered(widget::Widget* w) { | |||||
| if (w == dragHoveredWidget) | if (w == dragHoveredWidget) | ||||
| return; | return; | ||||
| if (dragHoveredWidget) { | if (dragHoveredWidget) { | ||||
| // Trigger DragLeave event | |||||
| DragLeave eDragLeave; | |||||
| // Trigger DragLeaveEvent | |||||
| Widget::DragLeaveEvent eDragLeave; | |||||
| eDragLeave.button = dragButton; | eDragLeave.button = dragButton; | ||||
| eDragLeave.origin = draggedWidget; | eDragLeave.origin = draggedWidget; | ||||
| dragHoveredWidget->onDragLeave(eDragLeave); | dragHoveredWidget->onDragLeave(eDragLeave); | ||||
| @@ -70,10 +70,10 @@ void State::setDragHovered(widget::Widget* w) { | |||||
| } | } | ||||
| if (w) { | if (w) { | ||||
| // Trigger DragEnter event | |||||
| Context cDragEnter; | |||||
| // Trigger DragEnterEvent | |||||
| EventContext cDragEnter; | |||||
| cDragEnter.target = w; | cDragEnter.target = w; | ||||
| DragEnter eDragEnter; | |||||
| Widget::DragEnterEvent eDragEnter; | |||||
| eDragEnter.context = &cDragEnter; | eDragEnter.context = &cDragEnter; | ||||
| eDragEnter.button = dragButton; | eDragEnter.button = dragButton; | ||||
| eDragEnter.origin = draggedWidget; | eDragEnter.origin = draggedWidget; | ||||
| @@ -82,29 +82,29 @@ void State::setDragHovered(widget::Widget* w) { | |||||
| } | } | ||||
| } | } | ||||
| void State::setSelected(widget::Widget* w) { | |||||
| void EventState::setSelected(widget::Widget* w) { | |||||
| if (w == selectedWidget) | if (w == selectedWidget) | ||||
| return; | return; | ||||
| if (selectedWidget) { | if (selectedWidget) { | ||||
| // Trigger Deselect event | |||||
| Deselect eDeselect; | |||||
| // Trigger DeselectEvent | |||||
| Widget::DeselectEvent eDeselect; | |||||
| selectedWidget->onDeselect(eDeselect); | selectedWidget->onDeselect(eDeselect); | ||||
| selectedWidget = NULL; | selectedWidget = NULL; | ||||
| } | } | ||||
| if (w) { | if (w) { | ||||
| // Trigger Select event | |||||
| Context cSelect; | |||||
| // Trigger SelectEvent | |||||
| EventContext cSelect; | |||||
| cSelect.target = w; | cSelect.target = w; | ||||
| Select eSelect; | |||||
| Widget::SelectEvent eSelect; | |||||
| eSelect.context = &cSelect; | eSelect.context = &cSelect; | ||||
| w->onSelect(eSelect); | w->onSelect(eSelect); | ||||
| selectedWidget = cSelect.target; | selectedWidget = cSelect.target; | ||||
| } | } | ||||
| } | } | ||||
| void State::finalizeWidget(widget::Widget* w) { | |||||
| void EventState::finalizeWidget(widget::Widget* w) { | |||||
| if (hoveredWidget == w) | if (hoveredWidget == w) | ||||
| setHovered(NULL); | setHovered(NULL); | ||||
| if (draggedWidget == w) | if (draggedWidget == w) | ||||
| @@ -117,14 +117,14 @@ void State::finalizeWidget(widget::Widget* w) { | |||||
| lastClickedWidget = NULL; | lastClickedWidget = NULL; | ||||
| } | } | ||||
| bool State::handleButton(math::Vec pos, int button, int action, int mods) { | |||||
| bool EventState::handleButton(math::Vec pos, int button, int action, int mods) { | |||||
| bool cursorLocked = APP->window->isCursorLocked(); | bool cursorLocked = APP->window->isCursorLocked(); | ||||
| widget::Widget* clickedWidget = NULL; | widget::Widget* clickedWidget = NULL; | ||||
| if (!cursorLocked) { | if (!cursorLocked) { | ||||
| // Trigger Button event | |||||
| Context cButton; | |||||
| Button eButton; | |||||
| // Trigger ButtonEvent | |||||
| EventContext cButton; | |||||
| Widget::ButtonEvent eButton; | |||||
| eButton.context = &cButton; | eButton.context = &cButton; | ||||
| eButton.pos = pos; | eButton.pos = pos; | ||||
| eButton.button = button; | eButton.button = button; | ||||
| @@ -142,8 +142,8 @@ bool State::handleButton(math::Vec pos, int button, int action, int mods) { | |||||
| setDragHovered(NULL); | setDragHovered(NULL); | ||||
| if (clickedWidget && draggedWidget) { | if (clickedWidget && draggedWidget) { | ||||
| // Trigger DragDrop event | |||||
| DragDrop eDragDrop; | |||||
| // Trigger DragDropEvent | |||||
| Widget::DragDropEvent eDragDrop; | |||||
| eDragDrop.button = dragButton; | eDragDrop.button = dragButton; | ||||
| eDragDrop.origin = draggedWidget; | eDragDrop.origin = draggedWidget; | ||||
| clickedWidget->onDragDrop(eDragDrop); | clickedWidget->onDragDrop(eDragDrop); | ||||
| @@ -163,8 +163,8 @@ bool State::handleButton(math::Vec pos, int button, int action, int mods) { | |||||
| if (clickedWidget | if (clickedWidget | ||||
| && clickTime - lastClickTime <= doubleClickDuration | && clickTime - lastClickTime <= doubleClickDuration | ||||
| && lastClickedWidget == clickedWidget) { | && lastClickedWidget == clickedWidget) { | ||||
| // Trigger DoubleClick event | |||||
| DoubleClick eDoubleClick; | |||||
| // Trigger DoubleClickEvent | |||||
| Widget::DoubleClickEvent eDoubleClick; | |||||
| clickedWidget->onDoubleClick(eDoubleClick); | clickedWidget->onDoubleClick(eDoubleClick); | ||||
| // Reset double click | // Reset double click | ||||
| lastClickTime = -INFINITY; | lastClickTime = -INFINITY; | ||||
| @@ -180,7 +180,7 @@ bool State::handleButton(math::Vec pos, int button, int action, int mods) { | |||||
| return !!clickedWidget; | return !!clickedWidget; | ||||
| } | } | ||||
| bool State::handleHover(math::Vec pos, math::Vec mouseDelta) { | |||||
| bool EventState::handleHover(math::Vec pos, math::Vec mouseDelta) { | |||||
| bool cursorLocked = APP->window->isCursorLocked(); | bool cursorLocked = APP->window->isCursorLocked(); | ||||
| // Fake a key RACK_HELD event for each held key | // Fake a key RACK_HELD event for each held key | ||||
| @@ -195,9 +195,9 @@ bool State::handleHover(math::Vec pos, math::Vec mouseDelta) { | |||||
| if (draggedWidget) { | if (draggedWidget) { | ||||
| bool dragHovered = false; | bool dragHovered = false; | ||||
| if (!cursorLocked) { | if (!cursorLocked) { | ||||
| // Trigger DragHover event | |||||
| Context cDragHover; | |||||
| DragHover eDragHover; | |||||
| // Trigger DragHoverEvent | |||||
| EventContext cDragHover; | |||||
| Widget::DragHoverEvent eDragHover; | |||||
| eDragHover.context = &cDragHover; | eDragHover.context = &cDragHover; | ||||
| eDragHover.button = dragButton; | eDragHover.button = dragButton; | ||||
| eDragHover.pos = pos; | eDragHover.pos = pos; | ||||
| @@ -206,13 +206,13 @@ bool State::handleHover(math::Vec pos, math::Vec mouseDelta) { | |||||
| rootWidget->onDragHover(eDragHover); | rootWidget->onDragHover(eDragHover); | ||||
| setDragHovered(cDragHover.target); | setDragHovered(cDragHover.target); | ||||
| // If consumed, don't continue after DragMove so Hover is not triggered. | |||||
| // If consumed, don't continue after DragMoveEvent so HoverEvent is not triggered. | |||||
| if (cDragHover.target) | if (cDragHover.target) | ||||
| dragHovered = true; | dragHovered = true; | ||||
| } | } | ||||
| // Trigger DragMove event | |||||
| DragMove eDragMove; | |||||
| // Trigger DragMoveEvent | |||||
| Widget::DragMoveEvent eDragMove; | |||||
| eDragMove.button = dragButton; | eDragMove.button = dragButton; | ||||
| eDragMove.mouseDelta = mouseDelta; | eDragMove.mouseDelta = mouseDelta; | ||||
| draggedWidget->onDragMove(eDragMove); | draggedWidget->onDragMove(eDragMove); | ||||
| @@ -221,9 +221,9 @@ bool State::handleHover(math::Vec pos, math::Vec mouseDelta) { | |||||
| } | } | ||||
| if (!cursorLocked) { | if (!cursorLocked) { | ||||
| // Trigger Hover event | |||||
| Context cHover; | |||||
| Hover eHover; | |||||
| // Trigger HoverEvent | |||||
| EventContext cHover; | |||||
| Widget::HoverEvent eHover; | |||||
| eHover.context = &cHover; | eHover.context = &cHover; | ||||
| eHover.pos = pos; | eHover.pos = pos; | ||||
| eHover.mouseDelta = mouseDelta; | eHover.mouseDelta = mouseDelta; | ||||
| @@ -236,7 +236,7 @@ bool State::handleHover(math::Vec pos, math::Vec mouseDelta) { | |||||
| return false; | return false; | ||||
| } | } | ||||
| bool State::handleLeave() { | |||||
| bool EventState::handleLeave() { | |||||
| heldKeys.clear(); | heldKeys.clear(); | ||||
| // When leaving the window, don't un-hover widgets because the mouse might be dragging. | // When leaving the window, don't un-hover widgets because the mouse might be dragging. | ||||
| // setDragHovered(NULL); | // setDragHovered(NULL); | ||||
| @@ -244,10 +244,10 @@ bool State::handleLeave() { | |||||
| return true; | return true; | ||||
| } | } | ||||
| bool State::handleScroll(math::Vec pos, math::Vec scrollDelta) { | |||||
| // Trigger HoverScroll event | |||||
| Context cHoverScroll; | |||||
| HoverScroll eHoverScroll; | |||||
| bool EventState::handleScroll(math::Vec pos, math::Vec scrollDelta) { | |||||
| // Trigger HoverScrollEvent | |||||
| EventContext cHoverScroll; | |||||
| Widget::HoverScrollEvent eHoverScroll; | |||||
| eHoverScroll.context = &cHoverScroll; | eHoverScroll.context = &cHoverScroll; | ||||
| eHoverScroll.pos = pos; | eHoverScroll.pos = pos; | ||||
| eHoverScroll.scrollDelta = scrollDelta; | eHoverScroll.scrollDelta = scrollDelta; | ||||
| @@ -256,10 +256,10 @@ bool State::handleScroll(math::Vec pos, math::Vec scrollDelta) { | |||||
| return !!cHoverScroll.target; | return !!cHoverScroll.target; | ||||
| } | } | ||||
| bool State::handleDrop(math::Vec pos, const std::vector<std::string>& paths) { | |||||
| // Trigger PathDrop event | |||||
| Context cPathDrop; | |||||
| PathDrop ePathDrop(paths); | |||||
| bool EventState::handleDrop(math::Vec pos, const std::vector<std::string>& paths) { | |||||
| // Trigger PathDropEvent | |||||
| EventContext cPathDrop; | |||||
| Widget::PathDropEvent ePathDrop(paths); | |||||
| ePathDrop.context = &cPathDrop; | ePathDrop.context = &cPathDrop; | ||||
| ePathDrop.pos = pos; | ePathDrop.pos = pos; | ||||
| rootWidget->onPathDrop(ePathDrop); | rootWidget->onPathDrop(ePathDrop); | ||||
| @@ -267,11 +267,11 @@ bool State::handleDrop(math::Vec pos, const std::vector<std::string>& paths) { | |||||
| return !!cPathDrop.target; | return !!cPathDrop.target; | ||||
| } | } | ||||
| bool State::handleText(math::Vec pos, int codepoint) { | |||||
| bool EventState::handleText(math::Vec pos, int codepoint) { | |||||
| if (selectedWidget) { | if (selectedWidget) { | ||||
| // Trigger SelectText event | |||||
| Context cSelectText; | |||||
| SelectText eSelectText; | |||||
| // Trigger SelectTextEvent | |||||
| EventContext cSelectText; | |||||
| Widget::SelectTextEvent eSelectText; | |||||
| eSelectText.context = &cSelectText; | eSelectText.context = &cSelectText; | ||||
| eSelectText.codepoint = codepoint; | eSelectText.codepoint = codepoint; | ||||
| selectedWidget->onSelectText(eSelectText); | selectedWidget->onSelectText(eSelectText); | ||||
| @@ -279,9 +279,9 @@ bool State::handleText(math::Vec pos, int codepoint) { | |||||
| return true; | return true; | ||||
| } | } | ||||
| // Trigger HoverText event | |||||
| Context cHoverText; | |||||
| HoverText eHoverText; | |||||
| // Trigger HoverText | |||||
| EventContext cHoverText; | |||||
| Widget::HoverTextEvent eHoverText; | |||||
| eHoverText.context = &cHoverText; | eHoverText.context = &cHoverText; | ||||
| eHoverText.pos = pos; | eHoverText.pos = pos; | ||||
| eHoverText.codepoint = codepoint; | eHoverText.codepoint = codepoint; | ||||
| @@ -290,7 +290,7 @@ bool State::handleText(math::Vec pos, int codepoint) { | |||||
| return !!cHoverText.target; | return !!cHoverText.target; | ||||
| } | } | ||||
| bool State::handleKey(math::Vec pos, int key, int scancode, int action, int mods) { | |||||
| bool EventState::handleKey(math::Vec pos, int key, int scancode, int action, int mods) { | |||||
| // Update heldKey state | // Update heldKey state | ||||
| if (action == GLFW_PRESS) { | if (action == GLFW_PRESS) { | ||||
| heldKeys.insert(key); | heldKeys.insert(key); | ||||
| @@ -302,9 +302,9 @@ bool State::handleKey(math::Vec pos, int key, int scancode, int action, int mods | |||||
| } | } | ||||
| if (selectedWidget) { | if (selectedWidget) { | ||||
| // Trigger SelectKey event | |||||
| Context cSelectKey; | |||||
| SelectKey eSelectKey; | |||||
| // Trigger SelectKeyEvent | |||||
| EventContext cSelectKey; | |||||
| Widget::SelectKeyEvent eSelectKey; | |||||
| eSelectKey.context = &cSelectKey; | eSelectKey.context = &cSelectKey; | ||||
| eSelectKey.key = key; | eSelectKey.key = key; | ||||
| eSelectKey.scancode = scancode; | eSelectKey.scancode = scancode; | ||||
| @@ -318,9 +318,9 @@ bool State::handleKey(math::Vec pos, int key, int scancode, int action, int mods | |||||
| return true; | return true; | ||||
| } | } | ||||
| // Trigger HoverKey event | |||||
| Context cHoverKey; | |||||
| HoverKey eHoverKey; | |||||
| // Trigger HoverKeyEvent | |||||
| EventContext cHoverKey; | |||||
| Widget::HoverKeyEvent eHoverKey; | |||||
| eHoverKey.context = &cHoverKey; | eHoverKey.context = &cHoverKey; | ||||
| eHoverKey.pos = pos; | eHoverKey.pos = pos; | ||||
| eHoverKey.key = key; | eHoverKey.key = key; | ||||
| @@ -334,15 +334,15 @@ bool State::handleKey(math::Vec pos, int key, int scancode, int action, int mods | |||||
| return !!cHoverKey.target; | return !!cHoverKey.target; | ||||
| } | } | ||||
| bool State::handleDirty() { | |||||
| // Trigger Dirty event | |||||
| Context cDirty; | |||||
| Dirty eDirty; | |||||
| bool EventState::handleDirty() { | |||||
| // Trigger DirtyEvent | |||||
| EventContext cDirty; | |||||
| Widget::DirtyEvent eDirty; | |||||
| eDirty.context = &cDirty; | eDirty.context = &cDirty; | ||||
| rootWidget->onDirty(eDirty); | rootWidget->onDirty(eDirty); | ||||
| return true; | return true; | ||||
| } | } | ||||
| } // namespace event | |||||
| } // namespace widget | |||||
| } // namespace rack | } // namespace rack | ||||
| @@ -12,10 +12,10 @@ | |||||
| #include <window.hpp> | #include <window.hpp> | ||||
| #include <asset.hpp> | #include <asset.hpp> | ||||
| #include <widget/Widget.hpp> | |||||
| #include <app/Scene.hpp> | #include <app/Scene.hpp> | ||||
| #include <keyboard.hpp> | #include <keyboard.hpp> | ||||
| #include <gamepad.hpp> | #include <gamepad.hpp> | ||||
| #include <event.hpp> | |||||
| #include <context.hpp> | #include <context.hpp> | ||||
| #include <patch.hpp> | #include <patch.hpp> | ||||
| #include <settings.hpp> | #include <settings.hpp> | ||||
| @@ -183,7 +183,7 @@ int main(int argc, char* argv[]) { | |||||
| contextSet(new Context); | contextSet(new Context); | ||||
| APP->engine = new engine::Engine; | APP->engine = new engine::Engine; | ||||
| if (!settings::headless) { | if (!settings::headless) { | ||||
| APP->event = new event::State; | |||||
| APP->event = new widget::EventState; | |||||
| APP->history = new history::State; | APP->history = new history::State; | ||||
| APP->window = new Window; | APP->window = new Window; | ||||
| APP->scene = new app::Scene; | APP->scene = new app::Scene; | ||||